from django.contrib.auth import authenticate
# 默认的第一个加密算法
class PBKDF2PasswordHasher(BasePasswordHasher): """ Secure password hashing using the PBKDF2 algorithm (recommended) Configured to use PBKDF2 + HMAC + SHA256. The result is a 64 byte binary string. Iterations may be changed safely but you must rename the algorithm if you change SHA256. """ algorithm = "pbkdf2_sha256" iterations = 36000 digest = hashlib.sha256 def encode(self, password, salt, iterations=None): assert password is not None assert salt and '$' not in salt if not iterations: iterations = self.iterations hash = pbkdf2(password, salt, iterations, digest=self.digest) hash = base64.b64encode(hash).decode('ascii').strip() return "%s$%d$%s$%s" % (self.algorithm, iterations, salt, hash) def verify(self, password, encoded): algorithm, iterations, salt, hash = encoded.split('$', 3) assert algorithm == self.algorithm encoded_2 = self.encode(password, salt, int(iterations)) return constant_time_compare(encoded, encoded_2) def safe_summary(self, encoded): algorithm, iterations, salt, hash = encoded.split('$', 3) assert algorithm == self.algorithm return OrderedDict([ (_('algorithm'), algorithm), (_('iterations'), iterations), (_('salt'), mask_hash(salt)), (_('hash'), mask_hash(hash)), ]) def must_update(self, encoded): algorithm, iterations, salt, hash = encoded.split('$', 3) return int(iterations) != self.iterations def harden_runtime(self, password, encoded): algorithm, iterations, salt, hash = encoded.split('$', 3) extra_iterations = self.iterations - int(iterations) if extra_iterations > 0: self.encode(password, salt, extra_iterations)
from django.contrib.auth.hashers import make_password
def make_password(password, salt=None, hasher='default'): """ Turn a plain-text password into a hash for database storage Same as encode() but generates a new random salt. If password is None then a concatenation of UNUSABLE_PASSWORD_PREFIX and a random string will be returned which disallows logins. Additional random string reduces chances of gaining access to staff or superuser accounts. See ticket #20079 for more info. """ if password is None: return UNUSABLE_PASSWORD_PREFIX + get_random_string(UNUSABLE_PASSWORD_SUFFIX_LENGTH) hasher = get_hasher(hasher) if not salt: salt = hasher.salt() return hasher.encode(password, salt)
from django.contrib.auth.hashers import check_password
def check_password(password, encoded, setter=None, preferred='default'): """ Returns a boolean of whether the raw password matches the three part encoded digest. If setter is specified, it'll be called when you need to regenerate the password. """ if password is None or not is_password_usable(encoded): return False preferred = get_hasher(preferred) hasher = identify_hasher(encoded) hasher_changed = hasher.algorithm != preferred.algorithm must_update = hasher_changed or preferred.must_update(encoded) is_correct = hasher.verify(password, encoded) # If the hasher didn't change (we don't protect against enumeration if it # does) and the password should get updated, try to close the timing gap # between the work factor of the current encoded password and the default # work factor. if not is_correct and not hasher_changed and must_update: hasher.harden_runtime(password, encoded) if setter and is_correct and must_update: setter(password) return is_correct
authenticate在处理用户登录验证时候的过程
import os os.environ.setdefault('DJANGO_SETTINGS_MODULE','django_auth.settings') from django.contrib.auth.hashers import ( check_password, is_password_usable, make_password, ) if __name__ == '__main__': raw_password = 'Qr3!JQc9bU@hrs2qjdqaE' password = make_password(raw_password) print(password) from django.conf import settings # print(settings.AUTHENTICATION_BACKENDS) # django.contrib.auth.backends.ModelBackend from django.utils.module_loading import import_string # for backend_path in settings.AUTHENTICATION_BACKENDS: # backend = import_string(backend_path)() # print(backend_path,backend) hashers_lst = settings.PASSWORD_HASHERS ''' [ 'django.contrib.auth.hashers.PBKDF2PasswordHasher', 'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher', 'django.contrib.auth.hashers.Argon2PasswordHasher', 'django.contrib.auth.hashers.BCryptSHA256PasswordHasher', 'django.contrib.auth.hashers.BCryptPasswordHasher'] ''' preferred = import_string(hashers_lst[0])() # <django.contrib.auth.hashers.PBKDF2PasswordHasher object at 0x0000000000B3BAC8> print(preferred.algorithm) from django.contrib.auth import hashers encoded = 'pbkdf2_sha256$36000$0EDgzLtVVT7o$nWQ4t3+iWKzv9p6MUfNIQPazaasadhYUtKt2ubLRCTA=' hasher = hashers.identify_hasher(encoded) # <django.contrib.auth.hashers.PBKDF2PasswordHasher object at 0x0000000000BB8978> print(hasher.algorithm) # pbkdf2_sha256 hasher_changed = hasher.algorithm != preferred.algorithm print(hasher_changed) # False is_correct = hasher.verify(raw_password, encoded) print(is_correct) algorithm, iterations, salt, hash = encoded.split('$', 3) print(algorithm, iterations, salt, hash) encoded2 = hasher.encode(raw_password, salt, int(iterations)) print(encoded2)
看源码,打印输出,是接近真相最便捷的途径。