Django

Code

Changeset 1327

Show
Ignore:
Timestamp:
11/20/05 21:33:22 (4 years ago)
Author:
adrian
Message:

Fixed #273 -- BACKWARDS-INCOMPATIBLE CHANGE -- Changed auth.User.password field to add support for other password encryption algorithms. Renamed password_md5 to password and changed field length from 32 to 128. See http://code.djangoproject.com/wiki/BackwardsIncompatibleChanges for upgrade information

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • django/trunk/django/models/auth.py

    r1224 r1327  
    3535    last_name = meta.CharField(_('last name'), maxlength=30, blank=True) 
    3636    email = meta.EmailField(_('e-mail address'), blank=True) 
    37     password_md5 = meta.CharField(_('password'), maxlength=32, help_text=_("Use an MD5 hash -- not the raw password.")) 
     37    password = meta.CharField(_('password'), maxlength=128, help_text=_("Use '[algo]$[salt]$[hexdigest]")) 
    3838    is_staff = meta.BooleanField(_('staff status'), help_text=_("Designates whether the user can log into this admin site.")) 
    3939    is_active = meta.BooleanField(_('active'), default=True) 
     
    5454        admin = meta.Admin( 
    5555            fields = ( 
    56                 (None, {'fields': ('username', 'password_md5')}), 
     56                (None, {'fields': ('username', 'password')}), 
    5757                (_('Personal info'), {'fields': ('first_name', 'last_name', 'email')}), 
    5858                (_('Permissions'), {'fields': ('is_staff', 'is_active', 'is_superuser', 'user_permissions')}), 
     
    7979 
    8080    def set_password(self, raw_password): 
    81         import md5 
    82         self.password_md5 = md5.new(raw_password).hexdigest() 
     81        import sha, random 
     82        algo = 'sha1' 
     83        salt = sha.new(str(random.random())).hexdigest()[:5] 
     84        hsh = sha.new(salt+raw_password).hexdigest() 
     85        self.password = '%s$%s$%s' % (algo, salt, hsh) 
    8386 
    8487    def check_password(self, raw_password): 
    85         "Returns a boolean of whether the raw_password was correct." 
    86         import md5 
    87         return self.password_md5 == md5.new(raw_password).hexdigest() 
     88        """ 
     89        Returns a boolean of whether the raw_password was correct. Handles 
     90        encryption formats behind the scenes. 
     91        """ 
     92        # Backwards-compatibility check. Older passwords won't include the 
     93        # algorithm or salt. 
     94        if '$' not in self.password: 
     95            import md5 
     96            is_correct = (self.password == md5.new(raw_password).hexdigest()) 
     97            if is_correct: 
     98                # Convert the password to the new, more secure format. 
     99                self.set_password(raw_password) 
     100                self.save() 
     101            return is_correct 
     102        algo, salt, hsh = self.password.split('$') 
     103        if algo == 'md5': 
     104            import md5 
     105            return hsh == md5.new(salt+raw_password).hexdigest() 
     106        elif algo == 'sha1': 
     107            import sha 
     108            return hsh == sha.new(salt+raw_password).hexdigest() 
     109        raise ValueError, "Got unknown password algorithm type in password." 
    88110 
    89111    def get_group_permissions(self): 
     
    177199    def _module_create_user(username, email, password): 
    178200        "Creates and saves a User with the given username, e-mail and password." 
    179         import md5 
    180         password_md5 = md5.new(password).hexdigest() 
    181201        now = datetime.datetime.now() 
    182         user = User(None, username, '', '', email.strip().lower(), password_md5, False, True, False, now, now) 
     202        user = User(None, username, '', '', email.strip().lower(), 'placeholder', False, True, False, now, now) 
     203        user.set_password(password) 
    183204        user.save() 
    184205        return user 
  • django/trunk/docs/authentication.txt

    r1302 r1327  
    4545    * ``last_name`` -- Optional. 30 characters or fewer. 
    4646    * ``email`` -- Optional. E-mail address. 
    47     * ``password_md5`` -- Required. An MD5 hash of the password. (Django 
    48       doesn't store the raw password.) Raw passwords can be arbitrarily long 
    49       and can contain any character
     47    * ``password`` -- Required. A hash of, and metadata about, the password. 
     48      (Django doesn't store the raw password.) Raw passwords can be arbitrarily 
     49      long and can contain any character. See the "Passwords" section below
    5050    * ``is_staff`` -- Boolean. Designates whether this user can access the 
    5151      admin site. 
     
    167167    >>> u.set_password('new password') 
    168168    >>> u.save() 
     169 
     170Passwords 
     171--------- 
     172 
     173**This only applies to the Django development version.** Previous versions, 
     174such as Django 0.90, used simple MD5 hashes without password salts. 
     175 
     176The ``password`` field of a ``User`` object is a string in this format:: 
     177 
     178    hashtype$salt$hash 
     179 
     180That's hashtype, salt and hash, separated by the dollar-sign character. 
     181 
     182Hashtype is either ``sha1`` (default) or ``md5``. Salt is a random string 
     183used to salt the raw password to create the hash. 
     184 
     185For example:: 
     186 
     187    sha1$a1976$a36cc8cbf81742a8fb52e221aaeab48ed7f58ab4 
     188 
     189The ``User.set_password()`` and ``User.check_password()`` functions handle 
     190the setting and checking of these values behind the scenes. 
    169191 
    170192Anonymous users