明文密码绝对不可行,因数据库泄露会导致所有账户失守,且HTTPS无法防止服务端日志、内存等意外暴露;必须用password_hash()生成带盐自适应哈希,并用password_verify()校验。

用户密码绝不能以明文形式存储或传输。PHP中唯一推荐的处理方式是使用 password_hash() 生成不可逆、带盐、自适应的哈希值,并用 password_verify() 进行安全校验。
为什么明文密码绝对不行
明文存储意味着数据库一旦泄露,所有用户账户立即失守。历史上多次重大数据泄露(如2012年某社交平台650万明文密码外泄)都源于此错误。即使传输层用了HTTPS,服务端仍可能在日志、调试信息、内存快照或备份中意外暴露明文,风险极高。
必须用 password_hash() 而非 MD5/SHA1
MD5、SHA1 等通用哈希函数速度快、无盐、无成本因子,极易被彩虹表或GPU暴力破解。它们不是为密码设计的——password_hash() 才是专为此场景打造的现代方案:
- 自动随机生成唯一盐值,无需手动拼接或管理
- 默认选用当前PHP最安全算法(如 bcrypt 或 Argon2ID),哈希字符串自带算法与参数标识
- 支持渐进式升级:用 password_needs_rehash() 检测旧哈希是否需重算
- 输出字符串可直接存入 VARCHAR(255) 字段,兼容未来算法扩展
推荐配置与实操要点
生产环境建议显式指定算法和参数,避免依赖 PASSWORD_DEFAULT 的隐式变更:
- 优先选 PASSWORD_ARGON2ID(PHP ≥ 7.3,需启用 Sodium 或 libargon2):抗ASIC/GPU更强,可调 memory_cost、time_cost、threads
- 次选 PASSWORD_BCRYPT(兼容性最好):设 cost = 12–14,在主流服务器上耗时约100–500ms,平衡安全与响应
- 验证时只调用 password_verify($input, $stored_hash) —— 它自动解析盐与参数,且采用恒定时间比对,防时序攻击
- 禁止用 ===、strcmp() 或自己写哈希逻辑比对,也不要在代码中记录或打印原始密码
传输环节同样关键
前端提交密码时,可用 <input type="password"> 隐藏显示,但不必在前端做额外哈希。重点保障传输安全:
- 强制全站 HTTPS,确保请求体中的明文密码在传输中加密
- 服务端禁用密码字段日志记录(如 Nginx、PHP-FPM、应用层日志均屏蔽 password 参数)
- 配合登录失败锁定、强密码策略、双因素认证等纵深防御措施



















