
django在用户密码更新后自动使当前会话失效,导致用户登出(变为匿名用户),这是出于安全默认行为;需调用`update_session_auth_hash()`保留登录状态。
在django中,当用户密码被修改(例如通过自定义视图 psswdReset)时,框架会主动使当前会话失效——即用户立即被登出,request.user.is_anonymous 变为 True。这一机制是Django内置的安全防护措施,目的是防止密码被篡改后旧会话仍可继续访问敏感资源(如会话劫持或凭证泄露场景下的横向移动)。
但对用户体验而言,这往往不理想:用户刚成功修改密码,却立刻跳转到登录页,需重新输入凭证。解决方法非常明确:在密码保存后,立即调用 update_session_auth_hash(request, user),通知Django该用户的认证凭据已更新,但当前会话仍可信,应予以延续。
以下是修复后的视图代码(关键修改已加注释):
from django.contrib.auth import update_session_auth_hash from django.contrib import messages from django.contrib.auth.hashers import check_password, make_password from django.shortcuts import render def psswdReset(request): if request.method == 'POST': new_psswd = request.POST.get('new_psswd') psswd = request.POST.get('psswd') # 验证原密码正确性(推荐使用 request.user.check_password() 更简洁) if not request.user.check_password(psswd): messages.error(request, 'Current password is incorrect.') return render(request, 'User/userPsswdReset.html') # 更新密码(推荐使用 set_password() 而非直接赋值 password 字段) request.user.set_password(new_psswd) request.user.save() # ✅ 关键一步:保持当前会话有效,避免自动登出 update_session_auth_hash(request, request.user) messages.success(request, 'Password changed successfully!') return render(request, 'User/userPsswdReset.html') return render(request, 'User/userPsswdReset.html')
? 注意事项与最佳实践:
- ✅ 始终使用 user.set_password() 替代手动 user.password = make_password(…),它会自动处理哈希逻辑并标记密码字段为已修改;
- ✅ 优先调用 request.user.check_password() 进行原密码校验,语义清晰且兼容自定义用户模型;
- ✅ update_session_auth_hash() 必须在 user.save() 之后、响应返回之前调用,否则无效;
- ⚠️ 切勿省略此调用——即使你认为“只是内部系统”,安全边界不应妥协;
- ? 若使用 Django 内置 PasswordChangeForm,该函数已被 PasswordChangeView 自动集成,无需手动处理。
通过以上调整,用户在修改密码后将保持登录态,体验更流畅,同时完全符合Django的安全设计原则。