Ticket #5600: django_auth_enhancements.diff

File django_auth_enhancements.diff, 6.0 KB (added by petrilli, 8 years ago)

Enhancements to django.contrib.auth, with documentation

  • django/conf/global_settings.py

     
    326326
    327327AUTHENTICATION_BACKENDS = ('django.contrib.auth.backends.ModelBackend',)
    328328
     329AUTH_CRYPTO_ALGORITHM = 'sha1'
     330
    329331LOGIN_URL = '/accounts/login/'
    330332
    331333LOGOUT_URL = '/accounts/logout/'
  • django/contrib/auth/models.py

     
     1from django.conf import settings
    12from django.contrib import auth
    23from django.core import validators
    34from django.core.exceptions import ImproperlyConfigured
     
    89from django.utils.translation import ugettext_lazy as _
    910import datetime
    1011import urllib
     12import base64
    1113
    1214UNUSABLE_PASSWORD = '!' # This will never be a valid hash
     15SALT_CHOICES = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
    1316
    1417try:
    1518    set
     
    1922def get_hexdigest(algorithm, salt, raw_password):
    2023    """
    2124    Returns a string of the hexdigest of the given plaintext password and salt
    22     using the given algorithm ('md5', 'sha1' or 'crypt').
     25    using the given algorithm ('md5', 'sha1', 'sha2', 'sha256', or 'crypt').
    2326    """
    2427    raw_password, salt = smart_str(raw_password), smart_str(salt)
    2528    if algorithm == 'crypt':
     
    3942        elif algorithm == 'sha1':
    4043            import sha
    4144            return sha.new(salt + raw_password).hexdigest()
     45        else:
     46            raise ValueError("Got unsupported password algorithm type in password.")
    4247    else:
    4348        if algorithm == 'md5':
    4449            return hashlib.md5(salt + raw_password).hexdigest()
    4550        elif algorithm == 'sha1':
    4651            return hashlib.sha1(salt + raw_password).hexdigest()
     52        elif algorithm == 'sha256' or algorithm == 'sha2':
     53            return hashlib.sha256(salt + raw_password).hexdigest()
    4754    raise ValueError("Got unknown password algorithm type in password.")
    4855
    4956def check_password(raw_password, enc_password):
     
    182189
    183190    def set_password(self, raw_password):
    184191        import random
    185         algo = 'sha1'
    186         salt = get_hexdigest(algo, str(random.random()), str(random.random()))[:5]
     192        algo = settings.AUTH_CRYPTO_ALGORITHM
     193        salt = ''.join([random.choice(SALT_CHOICES) for n in range(10)])
    187194        hsh = get_hexdigest(algo, salt, raw_password)
    188195        self.password = '%s$%s$%s' % (algo, salt, hsh)
    189196
     
    196203        # algorithm or salt.
    197204        if '$' not in self.password:
    198205            is_correct = (self.password == get_hexdigest('md5', '', raw_password))
    199             if is_correct:
    200                 # Convert the password to the new, more secure format.
    201                 self.set_password(raw_password)
    202                 self.save()
    203             return is_correct
    204         return check_password(raw_password, self.password)
     206        else:
     207            is_correct = check_password(raw_password, self.password)
     208        if is_correct:
     209            # Convert the password to the new, more secure format.
     210            self.convert_password(raw_password)
     211        return is_correct
    205212
    206213    def set_unusable_password(self):
    207214        # Sets a value that will never be a valid hash
     
    210217    def has_usable_password(self):
    211218        return self.password != UNUSABLE_PASSWORD
    212219
     220    def convert_password(self, raw_password):
     221        """
     222        Convert, in place, the user's password (raw_password). This will
     223        convert from any earlier version of password form, or to a new
     224        crypto algorithm as set in AUTH_CRYPTO_ALGORITHM. This will also
     225        expand the potential size of the salt.
     226        """
     227        algo, salt, password = self.password.split('$')
     228        if algo != settings.AUTH_CRYPTO_ALGORITHM or len(salt) < 10:
     229            self.set_password(raw_password)
     230            self.save()
     231
    213232    def get_group_permissions(self):
    214233        """
    215234        Returns a list of permission strings that this user has through
  • docs/settings.txt

     
    225225``CommonMiddleware`` is installed (see the `middleware docs`_). See also
    226226``PREPEND_WWW``.
    227227
     228AUTH_CRYPTO_ALGORITHM
     229---------------------
     230
     231Default: ``sha1``
     232
     233Determines the cryptograph algorithm to use in storing user passwords in the
     234database. Available options are ``sha1``, ``sha2``, ``sha256``, ``md5`` and
     235``crypto``. Note that ``sha2`` and ``sha256`` are synonyms.
     236
    228237CACHE_BACKEND
    229238-------------
    230239
  • docs/authentication.txt

     
    218218
    219219That's hashtype, salt and hash, separated by the dollar-sign character.
    220220
    221 Hashtype is either ``sha1`` (default), ``md5`` or ``crypt`` -- the algorithm
    222 used to perform a one-way hash of the password. Salt is a random string used
    223 to salt the raw password to create the hash. Note that the ``crypt`` method is
    224 only supported on platforms that have the standard Python ``crypt`` module
    225 available, and ``crypt`` support is only available in the Django development
    226 version.
     221Hashtype is either ``sha1`` (default), ``sha2``, ``sha256``, ``md5`` or
     222``crypt`` -- the algorithm used, based on the `AUTH_CRYPTO_ALGORITHM`_
     223setting, to perform a one-way hash of the password. Salt is a random string
     224used to salt the raw password to create the hash. Note that the ``crypt``
     225method is only supported on platforms that have the standard Python ``crypt``
     226module available, and ``crypt`` support is only available in the Django
     227development version.
    227228
    228229For example::
    229230
     
    237238converted automatically to the new style the first time ``User.check_password()``
    238239works correctly for a given user.
    239240
     241.. _AUTH_CRYPTO_ALGORITHM: ../settings/#auth-crypto-algorithm
     242
    240243Anonymous users
    241244---------------
    242245
Back to Top