Python Web 项目中密码该如何存储?
技术百科
冷炫風刃
发布时间:2026-01-20
浏览: 次 密码必须使用加盐哈希存储,优先选用bcrypt或scrypt等慢哈希算法,配合passlib或bcrypt库实现;数据库字段建议VARCHAR(255)或TEXT;校验须用恒定时间比较函数。
密码绝不能以明文形式存储,必须使用加盐哈希(salted hashing)处理。Python 生态中推荐使用 passlib 或内置的 secrets + hashlib 配合 bcrypt / scrypt 等现代算法,避免用 md5、sha1 或未加盐的哈希。
优先选用 bcrypt 或 scrypt 算法
这些是专为密码设计的慢哈希函数,能有效抵抗暴力破解和彩虹表攻击。它们自动处理加盐、迭代轮数等细节,开发者无需手动管理盐值。
- 安装
bcrypt:pip install bcrypt,然后用bcrypt.hashpw()生成哈希,bcrypt.checkpw()校验 - 更安全的替代是
passlib(支持多种后端),一行代码即可:from passlib.hash import bcrypt; hash = bcrypt.hash("password123") - 避免自己拼接盐和哈希,也不要重复实现加盐逻辑——出错概率高且易被绕过
数据库字段设计要兼容哈希长度
bcrypt 输出约 60 字符(如 b$...),scrypt 或 argon2 可能更长。字段类型建议用 VARCHAR(255) 或更大,别用 CHAR(60) 或短于 100 的长度,否则未来升级算法可能失败。
- PostgreSQL 可用
TEXT类型,MySQL 推荐VARCHAR(255) - 不要截断哈希字符串,哪怕看起来“长得一样”——截断后无法验证
- 若迁移旧系统,需保留原哈希格式标识(如前缀),便于后续识别算法并平滑升级
校验时始终用恒定时间比较
直接用 == 比较字符串可能引发时序攻击。虽然实际风险较低,但专业实现应避免。
-
bcrypt.checkpw()和passlib.verify()内部已使用恒定时间比较,直接调用即可 - 若自行实现(不推荐),请用
hmac.compare_digest(),而不是== - 注意:Web 框架如 Flask-Login、Django 的认证模块已内置安全校验,优先复用
额外防护建议
存储只是基础,还需配合其他措施提升整体安全性。
- 登录接口加速率限制(如 5 次失败后锁定 15 分钟),防暴力爆破
- 敏感操作(如改密、删账号)前要求二次验证(如当前密码或 MFA)
- 定期审计日志,记录登录失败、密码修改等关键事件
-
开发环境禁用密码重置邮件中的明文链接,生产环境强制 HTTPS + Token 限时
+单次有效
# 后端
# python
# 较低
# 推荐使用
# 还需
# 更长
# 专为
# 长得
# 更大
# mac
# https
# word
# go
# 字符串
# 接口
# 数据库
# 事件
# 算法
# Token
# char
# ssl
# mysql
# postgresql
# 开发环境
# 密码重置
# django
# flask
# 请用
# pip
# 绝不能
# 加盐
相关栏目:
<?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; ?>
】
相关推荐
- Win10如何更改网络连接_Windows10以太
- Win11怎么关闭小组件_Win11禁用任务栏天气
- Python脚本参数接收_sys与argparse
- Go 中实现 Python urllib.quot
- Win11怎么设置右键刷新选项_Windows11
- windows系统如何安装cab更新补丁_wind
- Windows10如何彻底关闭自动更新_Win10
- Win11如何设置省电模式 Win11开启电池节电
- Win10如何关闭安全中心所有通知 Win10禁用
- 如何在Golang中使用log包输出不同级别日志_
- Win11怎么设置默认图片查看器_Windows1
- php删除数据怎么加限制_带where条件删除避免
- Win11怎么更改账户头像_Windows 11自
- PythonPandas数据分析教程_数据清洗与处
- Win10怎么卸载金山毒霸_Win10彻底卸载金山
- Windows蓝屏错误0x00000018怎么处理
- Win11开机自检怎么关闭_跳过Win11开机磁盘
- Python路径拼接规范_跨平台处理说明【指导】
- 获取 PHP 文件最后修改时间的正确方法
- mac怎么安装adb_MAC配置Android A
- Python对象比较与排序_魔术方法解析【教程】
- MAC如何安装Git版本控制工具_MAC开发环境配
- Windows 10怎么录屏_Windows 10
- 如何使用Golang实现聊天室消息存档_存储聊天记
- 如何在Golang中实现邮件发送功能_Golang
- c++怎么实现大文件的分块读写_c++ 文件指针s
- Dapper的Execute方法的返回值是什么意思
- 如何在Golang中实现微服务负载均衡_Golan
- 如何更改Windows资源管理器的默认启动位置?(
- Win10如何备份驱动程序_Win10驱动备份步骤
- Windows10如何更改开机密码_Win10登录
- Win11怎么关闭通知消息_屏蔽Windows 1
- 如何使用Golang反射创建map对象_动态生成键
- c++如何用AFL++进行模糊测试 c++ Fuz
- c++ reinterpret_cast怎么用 c
- C++中的constexpr和const有什么区别
- php485读数据时阻塞怎么办_php485非阻塞
- c++的static关键字有什么用 静态变量和静态
- MAC如何快速搜索大文件_MAC磁盘空间分析与冗余
- Python大文件处理策略_内存优化说明【指导】
- Go语言中slice追加操作的底层共享机制详解
- c++的mutex和lock_guard如何使用
- Mac如何修复应用程序权限问题_Mac磁盘工具修复
- 如何使用Golang实现文件加密_Golang c
- Linux如何安装Tomcat应用服务器_Linu
- php修改数据怎么改富文本_update更新htm
- mac怎么看硬盘大小_MAC查看磁盘存储空间与文件
- 如何在 Go 中正确反序列化多个同级 XML 元素
- Win10怎样卸载自带Edge_Win10卸载Ed
- 如何优化Golang程序CPU性能_Golang


QQ客服