67

I'm building an app that has a separated front-end (Angular or some other JS library) and backend (Django). To ensure some security of requests being sent to the server, I want to append a url parameter say server/someurl?unique_id=Something-unique.

I am storing this unique code on the machine's localStorage for a specific time. However, I want to set this code using some sort of function on the server end which will not only generate this random alphanumeric text but also validate it based on incoming requests.

For example:

When a user opens the app, it'll send a server/setCode which will respond with this randomly generated string which I will store to Local Storage using JS.

On an outgoing request, say server/getdata?someparameter=some_data&unique_id=string_from_local_storage which the server can validate against the generating function and only then process the rest of the url.

Is there a package or a module that could help me achieve the generation and validation? I hope I could convey what I want as I'm not able to find any solution for this short of writing the function to generate and test myself.

Newtt
  • 6,050
  • 13
  • 68
  • 106
  • If all you need is a random string, you could use the stdlib `uuid` package. You can then just store that value in a sufficiently long `CharField`, or use one of the uuidfields available (or wait for django 1.8). – Matthew Schinckel Sep 20 '14 at 08:10

3 Answers3

195

Django provides the function get_random_string() which will satisfy the alphanumeric string generation requirement. You don't need any extra package because it's in the django.utils.crypto module.

>>> from django.utils.crypto import get_random_string
>>> unique_id = get_random_string(length=32)
>>> unique_id
u'rRXVe68NO7m3mHoBS488KdHaqQPD6Ofv'

You can also vary the set of characters with allowed_chars:

>>> short_genome = get_random_string(length=32, allowed_chars='ACTG')
>>> short_genome
u'CCCAAAAGTACGTCCGGCATTTGTCCACCCCT'

There are many other ways to generate a unique id, though not necessarily an alphanumeric one:

  1. The uuid module - generate a unique UUID using uuid1 or uuid4, e.g.

    >>> import uuid
    >>> my_uuid = uuid.uuid4()
    >>> my_uuid
    UUID('8e6eee95-eae1-4fb4-a436-27f68dbcb6d7')
    >>> str(my_uuid)
    '8e6eee95-eae1-4fb4-a436-27f68dbcb6d7'
    
  2. The random module:

    >>> import random
    >>> import string
    >>> allowed_chars = ''.join((string.ascii_letters, string.digits))
    >>> unique_id = ''.join(random.choice(allowed_chars) for _ in range(32))
    >>> unique_id
    '121CyaSHHzX8cqbgLnIg1C5qNrnv21uo'
    

Or, if you're not fussy about the alphabet:

>>> unique_id = '%32x' % random.getrandbits(16*8)
>>> unique_id
'5133d2d79ce518113474d8e9f3702638'
mhawke
  • 84,695
  • 9
  • 117
  • 138
  • Oh, wow! Thanks! How do I validate this string on incoming requests? – Newtt Sep 21 '14 at 09:48
  • @Newtt hmac.compare_digest – Aaron Zinman Jul 26 '17 at 23:41
  • Python 3 removed string.uppercase and string.lowercase so you need you use string.ascii_uppercase and string.ascii_lowercase instead – KrystianC Sep 06 '17 at 14:24
  • 1
    @KrystianC: thanks for noticing that. I've updated the answer to use `string.ascii_letters` which works for both versions of Python. – mhawke Sep 07 '17 at 00:11
  • 1
    Ugh, with regards to the `random` module, from the docs: "Warning: The pseudo-random generators of this module should not be used for security purposes. Use os.urandom() or SystemRandom if you require a cryptographically secure pseudo-random number generator. " – mlissner Jun 09 '18 at 15:25
  • @mlissner: that depends on the application, but the OP did mention using the random string for security purposes, so your comment is valid. You can do what Django's `get_random_string()` does and use [`random.SystemRandom()`](https://docs.python.org/3/library/random.html#random.SystemRandom) to use a OS provided random source instead. Just add `random = random.SystemRandom()` before calling `random.choice()`. – mhawke Jun 10 '18 at 06:58
8

From python 3.6, there is a secret module which has a specific method for generating safe random urls. It is the token_urlsafe method.

therealak12
  • 1,178
  • 2
  • 12
  • 26
0

You can use the nanoid:

https://github.com/puyuan/py-nanoid

from nanoid import generate

generate() # => NDzkGoTCdRcaRyt7GOepg
guettli
  • 25,042
  • 81
  • 346
  • 663