2023-07-22 09:57:16
在ThinkPHP中实现密码加密的核心方法是使用PHP内置的password_hash()和password_verify()函数,这是当前业界公认的密码安全最佳实践。以下是具体实现方式及关键要点:
一、核心函数使用方法password_hash()
作用:对明文密码进行哈希处理,自动加盐并调整计算成本。
参数:
$password:用户输入的明文密码。
$algo:哈希算法,推荐使用PASSWORD_DEFAULT(当前为bcrypt,随PHP版本自动升级)。
示例:
$hashedPassword = password_hash($password, PASSWORD_DEFAULT);password_verify()
作用:验证用户输入的明文密码与数据库存储的哈希值是否匹配。
参数:
$password:用户输入的明文密码。
$hashedPassword:数据库中存储的哈希值。
示例:
if (password_verify($password, $user['password'])) { // 密码正确}
在控制器中直接调用password_hash()处理密码,再存入数据库:
public function register() { $password = input('post.password'); $hashedPassword = password_hash($password, PASSWORD_DEFAULT); Db::name('user')->insert([ 'username' => input('post.username'), 'password' => $hashedPassword, 'create_time' => time() ]);}2. 用户登录验证(控制器层)使用password_verify()比对密码:
public function login() { $username = input('post.username'); $password = input('post.password'); $user = Db::name('user')->where('username', $username)->find(); if (!$user || !password_verify($password, $user['password'])) { return json(['code' => 1, 'msg' => '用户名或密码错误']); } return json(['code' => 0, 'msg' => '登录成功']);}三、推荐实践:模型层自动哈希为避免遗漏加密,建议在模型层通过set方法或事件监听实现密码自动哈希:
1. 使用set方法在模型中定义setPasswordAttr方法,自动处理密码字段:
namespace appindexmodel;use thinkModel;class User extends Model { public function setPasswordAttr($value) { return password_hash($value, PASSWORD_DEFAULT); }}效果:无论通过$user->save(['password' => $plainPassword])还是Db::name('user')->insert(...)操作,密码均会自动哈希。
2. 使用事件监听(可选)通过before_insert和before_update事件实现:
protected static function init() { self::event('before_insert', function ($user) { if (isset($user->password)) { $user->password = password_hash($user->password, PASSWORD_DEFAULT); } }); self::event('before_update', function ($user) { if (isset($user->password) && $user->isDirty('password')) { $user->password = password_hash($user->password, PASSWORD_DEFAULT); } });}
无盐(No Salt)MD5/SHA1无内置盐机制,相同密码的哈希值相同,易被攻击者通过彩虹表批量破解。
password_hash()优势:自动生成随机盐并嵌入哈希值,即使密码相同,哈希值也不同。
计算速度过快MD5/SHA1设计初衷是快速校验,但密码哈希需要“慢速”以抵御暴力破解。
password_hash()优势:支持调整计算成本(cost参数),显著增加破解时间。
彩虹表攻击MD5/SHA1的哈希值可被预计算并存储在彩虹表中,攻击者直接查表即可还原密码。
password_hash()优势:随机盐使彩虹表失效,每个密码需独立计算。
碰撞风险MD5/SHA1存在哈希碰撞(不同输入产生相同输出)的潜在漏洞。
password_hash()优势:使用更安全的算法(如bcrypt),碰撞概率极低。
