流程简单梳理

  1. - 入口
  2. from django.contrib.auth import authenticate
  3. user = authenticate(username=cd['username'], password=cd['password'])
  4. # If the given credentials are valid, return a User object.
  5.  
  6. - 获取全部用于认证的backend
  7. settings.AUTHENTICATION_BACKENDS
  8. Default: ['django.contrib.auth.backends.ModelBackend']
  9. # https://docs.djangoproject.com/en/1.11/ref/settings/#auth
  10.  
  11. - 遍历全部backend并执行认证操作
  12. user = _authenticate_with_backend(backend, backend_path, request, credentials)
  13. # credentials: { 'username':'xxx', 'password':'xxx' }
  14. 默认只有ModelBackend这个backend,认证是通过调用这个类里的authenticate函数
  15. - 通过username查找出user对象
  16. - user.check_password(password)
  17. # django.contrib.auth.base_user.AbstractBaseUser
  18. - AbstractBaseUser.check_password(self, raw_password)
  19. - django.contrib.auth.hashers.check_password(raw_password, self.password, setter)
  20. - 获取settings.PASSWORD_HASHERS里的第一个hash算法
  21. 默认是 django.contrib.auth.hashers.PBKDF2PasswordHasher
  22. - 根据self.password来找到当前用户的密码采用的hash算法
  23. - 判断用户密码采用的hash算法和当前默认的第一hash算法是否相同 (暂且只考虑相同的情况)
  24. - 把用户密码拆分成:algorithm, iterations, salt, hash,用iterationshash算法的iterations做对比是否一致
  25. - 验证:hasher.verify(password, encoded)
  26. - 把用户输入的密码进行加密:先用hashlib.sha256,然后在用base64.b64encode最终计算出一个hash
  27. - 然后把 self.algorithm, iterations, salt, hash 组合成一个字符串,记作encoded_2
  28. - 把用户真实密码和encoded_2作比较,看看是否相同
  29. - user_can_authenticate(user)
  30. - 判断当前用户的 is_active

from django.contrib.auth import authenticate

# 默认的第一个加密算法

  1. class PBKDF2PasswordHasher(BasePasswordHasher):
  2. """
  3. Secure password hashing using the PBKDF2 algorithm (recommended)
  4.  
  5. Configured to use PBKDF2 + HMAC + SHA256.
  6. The result is a 64 byte binary string. Iterations may be changed
  7. safely but you must rename the algorithm if you change SHA256.
  8. """
  9. algorithm = "pbkdf2_sha256"
  10. iterations = 36000
  11. digest = hashlib.sha256
  12.  
  13. def encode(self, password, salt, iterations=None):
  14. assert password is not None
  15. assert salt and '$' not in salt
  16. if not iterations:
  17. iterations = self.iterations
  18. hash = pbkdf2(password, salt, iterations, digest=self.digest)
  19. hash = base64.b64encode(hash).decode('ascii').strip()
  20. return "%s$%d$%s$%s" % (self.algorithm, iterations, salt, hash)
  21.  
  22. def verify(self, password, encoded):
  23. algorithm, iterations, salt, hash = encoded.split('$', 3)
  24. assert algorithm == self.algorithm
  25. encoded_2 = self.encode(password, salt, int(iterations))
  26. return constant_time_compare(encoded, encoded_2)
  27.  
  28. def safe_summary(self, encoded):
  29. algorithm, iterations, salt, hash = encoded.split('$', 3)
  30. assert algorithm == self.algorithm
  31. return OrderedDict([
  32. (_('algorithm'), algorithm),
  33. (_('iterations'), iterations),
  34. (_('salt'), mask_hash(salt)),
  35. (_('hash'), mask_hash(hash)),
  36. ])
  37.  
  38. def must_update(self, encoded):
  39. algorithm, iterations, salt, hash = encoded.split('$', 3)
  40. return int(iterations) != self.iterations
  41.  
  42. def harden_runtime(self, password, encoded):
  43. algorithm, iterations, salt, hash = encoded.split('$', 3)
  44. extra_iterations = self.iterations - int(iterations)
  45. if extra_iterations > 0:
  46. self.encode(password, salt, extra_iterations)

from django.contrib.auth.hashers import make_password

  1. def make_password(password, salt=None, hasher='default'):
  2. """
  3. Turn a plain-text password into a hash for database storage
  4.  
  5. Same as encode() but generates a new random salt.
  6. If password is None then a concatenation of
  7. UNUSABLE_PASSWORD_PREFIX and a random string will be returned
  8. which disallows logins. Additional random string reduces chances
  9. of gaining access to staff or superuser accounts.
  10. See ticket #20079 for more info.
  11. """
  12. if password is None:
  13. return UNUSABLE_PASSWORD_PREFIX + get_random_string(UNUSABLE_PASSWORD_SUFFIX_LENGTH)
  14. hasher = get_hasher(hasher)
  15.  
  16. if not salt:
  17. salt = hasher.salt()
  18.  
  19. return hasher.encode(password, salt)

from django.contrib.auth.hashers import check_password

  1. def check_password(password, encoded, setter=None, preferred='default'):
  2. """
  3. Returns a boolean of whether the raw password matches the three
  4. part encoded digest.
  5.  
  6. If setter is specified, it'll be called when you need to
  7. regenerate the password.
  8. """
  9. if password is None or not is_password_usable(encoded):
  10. return False
  11.  
  12. preferred = get_hasher(preferred)
  13. hasher = identify_hasher(encoded)
  14.  
  15. hasher_changed = hasher.algorithm != preferred.algorithm
  16. must_update = hasher_changed or preferred.must_update(encoded)
  17. is_correct = hasher.verify(password, encoded)
  18.  
  19. # If the hasher didn't change (we don't protect against enumeration if it
  20. # does) and the password should get updated, try to close the timing gap
  21. # between the work factor of the current encoded password and the default
  22. # work factor.
  23. if not is_correct and not hasher_changed and must_update:
  24. hasher.harden_runtime(password, encoded)
  25.  
  26. if setter and is_correct and must_update:
  27. setter(password)
  28. return is_correct

authenticate在处理用户登录验证时候的过程

  1. import os
  2. os.environ.setdefault('DJANGO_SETTINGS_MODULE','django_auth.settings')
  3.  
  4. from django.contrib.auth.hashers import (
  5. check_password, is_password_usable, make_password,
  6. )
  7.  
  8. if __name__ == '__main__':
  9. raw_password = 'Qr3!JQc9bU@hrs2qjdqaE'
  10. password = make_password(raw_password)
  11.  
  12. print(password)
  13.  
  14. from django.conf import settings
  15. # print(settings.AUTHENTICATION_BACKENDS) # django.contrib.auth.backends.ModelBackend
  16. from django.utils.module_loading import import_string
  17.  
  18. # for backend_path in settings.AUTHENTICATION_BACKENDS:
  19. # backend = import_string(backend_path)()
  20. # print(backend_path,backend)
  21.  
  22. hashers_lst = settings.PASSWORD_HASHERS
  23. '''
  24. [
  25. 'django.contrib.auth.hashers.PBKDF2PasswordHasher',
  26. 'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher',
  27. 'django.contrib.auth.hashers.Argon2PasswordHasher',
  28. 'django.contrib.auth.hashers.BCryptSHA256PasswordHasher',
  29. 'django.contrib.auth.hashers.BCryptPasswordHasher']
  30. '''
  31. preferred = import_string(hashers_lst[0])()
  32. # <django.contrib.auth.hashers.PBKDF2PasswordHasher object at 0x0000000000B3BAC8>
  33. print(preferred.algorithm)
  34. from django.contrib.auth import hashers
  35. encoded = 'pbkdf2_sha256$36000$0EDgzLtVVT7o$nWQ4t3+iWKzv9p6MUfNIQPazaasadhYUtKt2ubLRCTA='
  36. hasher = hashers.identify_hasher(encoded)
  37. # <django.contrib.auth.hashers.PBKDF2PasswordHasher object at 0x0000000000BB8978>
  38. print(hasher.algorithm) # pbkdf2_sha256
  39.  
  40. hasher_changed = hasher.algorithm != preferred.algorithm
  41.  
  42. print(hasher_changed) # False
  43.  
  44. is_correct = hasher.verify(raw_password, encoded)
  45. print(is_correct)
  46.  
  47. algorithm, iterations, salt, hash = encoded.split('$', 3)
  48. print(algorithm, iterations, salt, hash)
  49. encoded2 = hasher.encode(raw_password, salt, int(iterations))
  50. print(encoded2)

看源码,打印输出,是接近真相最便捷的途径。  

authenticate验证的流程的更多相关文章

  1. https申请证书并部署到网站流程,浏览器验证证书流程

    https申请证书并部署到网站流程: 1.生成一对秘钥,设公钥为pubk1,私钥为prik12.假设发布的网站地址为https://www.example.com3.生成一个CSR文件(Cerific ...

  2. Token验证的流程及如何准确的判断一个数据的类型

    Token验证的流程: 1,客户端使用用户名跟密码请求登录:2,服务端收到请求,去验证用户名与密码:3,验证成功后,服务端会签发一个 Token,再把这个 Token 发送给客户端:4,客户端收到 T ...

  3. authenticate的执行流程与重写

    流程 1.authenticate调用的是_get_backends函数 def authenticate(request=None, **credentials): for backend, bac ...

  4. springcloud +spring security多种验证方式之第三方token生成自己的token通过校验和自己的表单验证大体流程

    步骤: 1.继承 WebSecurityConfigurerAdapter.class,其中使用两个过滤器,一个spring scurity自带的UsernamePasswordAuthenticat ...

  5. Shiro -- (二) 身份验证基本流程

    简介: 在 shiro 中,用户需要提供 principals (身份)和 credentials(证明)给 shiro,从而应用能验证用户身份: principals:身份,即主体的标识属性,可以是 ...

  6. Apache shiro之身份验证(登陆)流程

    从张开涛blog学习后整理:http://jinnianshilongnian.iteye.com/blog/2018398 上图中的类和接口都可以继承和实现来个性化自己的实现. 其中重点看一下Mod ...

  7. SharePoint2010 Form验证配置流程

    1.修改管理中心的Web.config文件,位置:C:\inetpub\wwwroot\wss\VirtualDirectories\42903 2.修改应用程序的Web.config文件,位置:C: ...

  8. 【ASP.NET】编程点滴 :ASP.NET身份验证

    ASP.NET实际开发中身份验证 是一个不可回避的问题.在相当一段长的时间内,由于不求甚解,我对这个话题似懂非懂.今天就对它做个简单的小结. Authentication and Authorizat ...

  9. ASP.NET Forms身份验证概述

    表单身份验证允许您使用自己的代码对用户进行身份验证,然后在cookie或页面URL中维护身份验证令牌.表单身份验证通过FormsAuthenticationModule类参与ASP.NET页面生命周期 ...

随机推荐

  1. 自定义Qt构建步骤,添加数据文件(txt,json等)到构建目录

    Qt的qrc资源文件是只读的,因此我们如果要用txt之类的文件存储数据,在程序运行过程中就不能对它们进行修改,也就是不能进行读操作.用"file.open(QIODevice::WriteO ...

  2. 使用nmon监控Linxu服务器性能

    nmon是IBM开发的Linux软件工具.能够监控多项Linux服务,最常见的如:CPU使用率.内存使用率.硬盘读写.网卡流量等. 并能设置参数,将记录的数据保存到文件,利用Excel做统计分析. 安 ...

  3. 洛谷P5069 [Ynoi2015]纵使日薄西山(树状数组,set)

    洛谷题目传送门 一血祭 向dllxl致敬! 算是YNOI中比较清新的吧,毕竟代码只有1.25k. 首先我们对着题意模拟,寻找一些思路. 每次选了一个最大的数后,它和它周围两个数都要减一.这样无论如何, ...

  4. Centos 7.3 安装Grafana 6.0

    grafana简介 Grafana是一个完全开源的度量分析与可视化平台,可对来自各种各种数据源的数据进行查询.分析.可视化处理以及配置告警. Grafana支持的数据源: 官方:Graphite,In ...

  5. 【转】gcc 编译使用动态链接库和静态链接库

    1 库的分类 根据链接时期的不同,库又有静态库和动态库之分. 静态库是在链接阶段被链接的(好像是废话,但事实就是这样),所以生成的可执行文件就不受库的影响了,即使库被删除了,程序依然可以成功运行. 有 ...

  6. 如何 通过 userAgent 区别微信小程序

    微信内置浏览器: 微信小程序: 有micromessenger是微信内置浏览器,有micromessenger和miniprogram的是微信小程序.  (ios不适用) if(navigator.u ...

  7. HDU/HDOJ 4699 Editor

    对顶栈算法. 此题充分说明了cin的不中以及scanf的优越性. 我TM用cin超时了!!!换成scanf就A了!!! #include <cstdio> #include <cst ...

  8. tyvj/joyoi 1340 送礼物

    论搜索顺序的优越性. 从小到大搜索,T到怀疑人生. 从大到小搜索,轻松AC. 双向搜索. 是这样的.我们首先排序一下,然后翻转.(当然也可以写cmp) 然后我们搜前半部分,把结果记录在某一数组中. 然 ...

  9. 【Asia Yokohama Regional Contest 2018】Arithmetic Progressions

    题目大意:给定 N(1<N<=5000) 个不同元素组成的集合,求从中选出若干数字组成的等差数列最长是多少. 题解:直接暴力有 \(O(n^3)\) 的算法,即:枚举等差数列的前两个值,再 ...

  10. django2 用iframe标签完成 网页内嵌播放b站视频功能

    前言: 给自己的网站中加入视频资源,有两种方法,一种是用iframe标签引用外站资源,另一种则使用video标签,获取站内资源进行视频播放.其中前者顾名思义,是将视频资源上传到视频网站中,然后通过引用 ...