如何在 Django 中修改用户密码后保持会话不丢失
技术百科
碧海醫心
发布时间:2026-01-01
浏览: 次 django 默认会在用户密码变更后自动失效旧会话,导致用户登出;解决方法是调用 `update_session_auth_hash()` 保留当前登录状态。
在 Django 中,当用户密码被修改(例如通过自定义视图 psswdReset),框架出于安全考虑会主动使所有基于旧密码的会话失效——这是默认行为,并非 Bug。其原理在于:Django 的认证中间件会比对当前 session 中存储的哈希签名与用户 password 字段的哈希值。一旦 user.password 被直接更新(如 user.password = make_password(...)),而未同步更新 session 的认证标识,下次请求时 AuthenticationMiddleware 将检测到不一致,强制将 request.user 置为 AnonymousUser,即“会话被冲刷”。
您当前的代码存在两个关键问题:
- 未调用 update_session_auth_hash():这是最核心的修复点;
- 手动赋值 user.password 并保存:虽可行,但绕过了 Django 用户模型的安全更新逻辑,易遗漏信号或钩子。
✅ 正确做法如下(推荐使用 set_password() + update_session_auth_hash()):
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')
# 验证原密码正确性
if not request.user.check_password(psswd):
messages.error(request, 'Current password is incorrect.')
return render(request, 'User/userPsswdReset.html')
# 安全设置新密码(自动哈希)
request.user.set_password(new_psswd)
request.user.save()
# ? 关键:更新 session 认证哈希,防止登出
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')? 注意事项:
- update_session_auth_hash(request, user) 必须在 user.save() 之后调用,且 user 必须是当前已认证的用户实例(通常为 request.user);
- 不要使用 check_password(psswd, request.user.password) 手动比对——应直接调用 request.user.check_password(),它更安全且兼容自定义密码 hasher;
- 若使用 CustomUser 模型,请确保其继承自 AbstractBaseUser 或 AbstractUser,并正确实现了 set_password() 方法;
- 该机制仅影响当前用户的活跃会话,其他设备/浏览器的会话仍会被安全地注销(符合预期)。
? 总结:密码修改后会话丢失是 Django 的主动安全防护机制,而非缺陷。只需在保存新密码后调用 update_session_auth_hash(),即可在保障安全性的同时提供无缝的用户体验。
# 解决方法
# 安全防护
# 浏览器
# word
# go
# html
# session
# 中间件
# django
相关栏目:
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
AI推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
SEO优化<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
技术百科<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
谷歌推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
百度推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
网络营销<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
案例网站<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
精选文章<?muma echo $count; ?>
】
相关推荐
- 如何在 VS Code 中正确配置并使用 NumP
- PHP cURL GET请求:正确设置请求头与身份
- 如何在Golang中处理URL参数_Golang
- 如何在Golang中编写端到端测试_Golang
- Python 中将 ISO 8601 时间戳转换为
- Win11怎么设置组合键快捷方式_Windows1
- Win11怎么关闭粘滞键_彻底禁用Windows
- Win11怎么连接蓝牙耳机_Win11蓝牙设备配对
- Win11怎么关闭透明效果_Windows11个性
- 如何使用Golang捕获并记录协程panic_保证
- Drupal 中 HTML 链接被双重转义导致渲染
- Win11怎么关闭用户账户控制UAC_Window
- Python路径拼接规范_跨平台处理说明【指导】
- Windows11怎么自定义任务栏_Windows
- Win10怎么关闭自动更新错误弹窗_Win10策略
- VSC怎样在VSC中调试PHPAPI_接口调试技巧
- Python迭代器生成器进阶教程_节省内存与懒加载
- Go 中的 := 运算符:类型推导机制与使用边界详
- PHP中require语句后直接调用返回对象方法的
- Win11怎么关闭定位服务_保护Win11位置隐私
- Win11任务栏怎么调到左边_Win11开始菜单居
- C++如何获取CPU核心数?(std::threa
- 如何在Golang中处理数据库事务错误_回滚和日志
- Win11怎么设置应用分屏_Windows11贴靠
- php485在php5.6下能用吗_php485旧
- Win11搜索栏无法输入_解决Win11开始菜单搜
- windows如何测试网速_windows系统网络
- 如何在Golang中实现自定义Benchmark_
- mac怎么查看wifi密码_MAC查看已连接WiF
- Win11怎么禁用键盘自带键盘_Win11笔记本禁
- Mac系统更新下载慢或失败怎么办_解决macOS升
- 如何在JavaScript中动态拼接PHP的bas
- 如何使用Golang实现容器自动化运维_Golan
- Win11如何设置省电模式 Win11开启电池节电
- Windows10系统怎么查看显卡驱动_Win10
- Win10如何卸载预装Edge扩展_Win10卸载
- Win11怎么压缩文件 Win11自带压缩解压功能
- php下载安装包怎么选_threadsafe与nt
- Windows怎样关闭Edge新标签页广告_Win
- Windows 11怎么更改锁屏超时时间_Wind
- 如何在Golang中写入JSON文件_保存结构体数
- C++如何使用std::optional?(处理可
- Win11怎么设置开机密码_Windows11账户
- Mac如何开启夜览模式_Mac护眼模式设置与定时
- Windows10蓝屏代码DPC_WATCHDOG
- Mac如何与安卓手机传文件_Mac和Android
- 如何使用 Selenium 正确获取篮球参考网站球
- Win11怎么设置默认输入法 Win11固定中文输
- Win11怎么检查TPM2.0模块_Windows
- PHP主流架构怎么集成Redis缓存_配置步骤【方

.user)
messages.success(request, 'Password changed successfully!')
return render(request, 'User/userPsswdReset.html')
return render(request, 'User/userPsswdReset.html')
QQ客服