用户在手机上改了密码,电脑上的登录为什么立刻失效?为什么改密码的这台设备自己也被登出了?Django 是怎么做到的?这篇用两个「设备」把机制和例外都跑一遍。
session 里的 hash = 5696a8ff42b8ccb1… 用户密码哈希 = pbkdf2_sha256$1500000$17… u.get_session_auth_hash() 与 session 里一致: True 改密码后 get_session_auth_hash() 与旧 session 里的一致: False
密码哈希变了,派生出来的 session hash 就变了。这也是 SESSION_ENGINE = signed_cookies 时仍能「登出所有设备」的原因(第 79 篇)。
改密码前 A: {'user': 'u'} B: {'user': 'u'}
A 上改密码(不调用 update_session_auth_hash)之后 A: {'user': 'AnonymousUser'} B: {'user': 'AnonymousUser'}
A 上改密码并调用 update_session_auth_hash(request, user) 之后 A: {'user': 'u'} B: {'user': 'AnonymousUser'}一个已登录请求的查询: 2 次(session + user);校验 hash 不额外查询
Django 自带的 PasswordChangeView 内部会调用 update_session_auth_hash;自己写改密码视图时一定别忘。
只改 last_login 之后: {'user': 'u'}
重新哈希同一个密码(盐不同)之后: {'user': 'AnonymousUser'}校验用的是用户对象里已经取出的密码哈希,不需要额外查询。
删除了 2 个 session;A: {'user': 'AnonymousUser'} B: {'user': 'AnonymousUser'}删除 session 行只适用于数据库(或缓存)后端;cookie 后端要靠让 hash 变化。