yii框架默认使用pbkdf2+sha256(10000轮迭代)进行单向密码哈希,而非可逆加密;generatepasswordhash()自动生成含盐哈希值,validatepassword()自动验证,确保密码不可逆、抗暴力破解与彩虹表攻击。

Yii 框架默认不直接“加密”密码,而是用 PBKDF2(通过 Security::generatePasswordHash())进行**密钥派生哈希**——这是当前存储用户密码的正确做法,比单纯 MD5 或 AES 加密更安全。
为什么不用 encrypt() 存密码?
加密(encrypt/decrypt)是可逆的,一旦密钥泄露,所有密码瞬间还原;而密码哈希是单向的,攻击者只能暴力碰撞。Yii 的 Security 组件压根没提供对称加密接口存密码,强行用 Crypt::encrypt()(Laravel 风格)或 sodium_crypto_secretbox() 是反模式。
- 框架内置的
User::loginByPassword()和IdentityInterface::validatePassword()只认哈希值,不认密文 -
Security::validatePassword($input, $hash)内部自动处理盐、迭代轮数、算法版本,你只需传入原始密码和数据库里存的哈希串 - 哈希值形如
$2y$13$...(bcrypt)或$pbkdf2-sha256$...(Yii 默认),自带盐和参数,无需额外存 salt 字段
实际怎么生成和验证密码哈希?
在用户注册或修改密码时调用 Security::generatePasswordHash(),验证登录时用 Security::validatePassword():
// 生成(例如在 User::signup() 中)
$security = Yii::$app->getSecurity();
$user->password_hash = $security->generatePasswordHash($this->password);
// 验证(例如在 IdentityInterface 实现中)
public function validatePassword($password)
{
return Yii::$app->getSecurity()->validatePassword($password, $this->password_hash);
}
-
generatePasswordHash()默认使用PBKDF2+SHA256,10000 轮迭代(可配置$cost参数微调) - 不要手动指定算法或硬编码 salt——Yii 已全包办,改了反而破坏兼容性
- 若需兼容旧 bcrypt 哈希(如从其他系统迁移),可启用
useBcrypt配置,但非必要不建议切换
常见错误:把哈希当加密来回解
有人看到 password_hash 字段里是长字符串,就以为能“解密”回明文,于是写 Security::decrypt() 或尝试 base64_decode —— Yii 根本没有 decrypt() 方法用于密码,这种代码会报 Call to undefined method 错误。
- 密码字段永远只写入哈希值,绝不存明文、绝不存可逆密文
- 忘记密码必须走「重置流程」(发 token 链接),而不是「找回密码」
- 日志、调试输出、数据库 dump 中避免打印
password_hash全值(虽不可逆,但暴露哈希可能助攻击者离线爆破)
真正容易被忽略的是:哈希强度依赖于 PHP 环境是否启用 openssl 和 libsodium 扩展——如果缺失,Yii 会降级到较弱的 fallback 实现,但不会报错。上线前务必检查 phpinfo() 或运行 var_dump(extension_loaded('sodium')); 确认扩展可用。











