
django 默认在用户密码变更时使旧会话失效,导致用户被登出;需调用 `update_session_auth_hash()` 保持登录状态。
在 Django 中,当用户密码被修改(尤其是通过 user.set_password() 或直接更新 user.password 字段)后,框架会自动使所有基于旧密码哈希生成的会话失效——这是出于安全考虑的默认行为:防止密码泄露后攻击者继续利用已存在的会话令牌。因此,即使用户仍在浏览页面,request.user 也会变为匿名(is_anonymous=True),看似“意外登出”。
你当前的视图中存在两个关键问题:
- 未调用 update_session_auth_hash():这是解决该问题的核心。它会重新生成并更新当前会话的认证哈希,使其与新密码匹配;
- 手动赋值 user.password = make_password(...) 不推荐:应优先使用 user.set_password(),它不仅加密密码,还会自动处理盐值、算法升级等细节,并兼容后续的 session hash 更新。
✅ 正确做法如下(已修复):
51shop 由 PHP 语言开发, 使用快速的 MySQL 数据库保存数据 ,为中小型网站实现网上电子商务提供一个完美的解决方案.一、用户模块1. 用户注册:用户信息包括:用户ID、用户名、用户密码、性别、邮箱、省份、城市、 联系电话等信息,用户注册后不能立即使用,需由管理员激活账号,才可使用(此功能管理员可设置)2. 登录功能3. 资料修改:用户可修改除账号以后的所有资料4. 忘记密码:要求用
from django.contrib.auth import update_session_auth_hash
from django.contrib import messages
def psswdReset(request):
if request.method == 'POST':
new_psswd = request.POST.get('new_psswd')
psswd = request.POST.get('psswd')
# 验证原密码(注意:check_password 接收明文 vs 哈希)
if check_password(psswd, request.user.password):
user = request.user # 直接使用 request.user,无需重复查询
user.set_password(new_psswd) # ✅ 推荐方式:自动处理加密与兼容性
user.save()
# ✅ 关键一步:更新当前会话的认证哈希,避免登出
update_session_auth_hash(request, user)
messages.success(request, 'Password changed successfully!')
return render(request, 'User/userPsswdReset.html', {})
return render(request, 'User/userPsswdReset.html', {})⚠️ 注意事项:
- update_session_auth_hash() 必须在 user.save() 之后、响应返回之前调用;
- 它仅影响当前请求的会话,其他设备/浏览器的会话仍会失效(符合安全设计);
- 若使用 authenticate() + login() 流程(如登录页),无需手动调用此函数——login() 内部已自动处理;
- 切勿跳过原密码校验(即 check_password),否则将削弱账户安全性。
总结:Django 的会话自动失效机制是主动的安全防护,而非 bug;正确使用 update_session_auth_hash() 即可在保障安全的前提下提供无缝的密码更新体验。









