本文目录导读:

在Laravel中,密码哈希和验证是通过Illuminate\Contracts\Hashing\Hasher接口实现的,默认使用BcryptHasher,以下是完整的验证过程:
密码哈希创建
Bcrypt 哈希过程
// Laravel 使用 bcrypt 算法生成密码哈希
$hashedPassword = Hash::make('password123');
// 输出示例
// $2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi
哈希格式解析:
$2y$- 算法标识(bcrypt)10- 成本因子(cost factor,默认为10)- 后续字符 - 22字符的盐值 + 31字符的哈希值
密码验证过程
完整验证流程
步骤1:获取用户记录
$user = User::where('email', $request->email)->first();
步骤2:调用验证方法
// 方式1:使用 Auth 门面
if (Auth::attempt(['email' => $email, 'password' => $password])) {
// 认证成功
}
// 方式2:手动验证
if (Hash::check($request->password, $user->password)) {
// 密码正确
}
// 方式3:使用 Auth::validate()
$credentials = ['email' => $email, 'password' => $password];
if (Auth::validate($credentials)) {
// 验证成功
}
步骤3:内部验证机制
// BcryptHasher 的 check 方法
public function check($value, $hashedValue, array $options = [])
{
if (strlen($hashedValue) === 0) {
return false;
}
return password_verify($value, $hashedValue);
}
实际验证原理
Bcrypt 验证过程
// PHP 内置的 password_verify 函数
public function verifyPassword($plainPassword, $hashedPassword) {
/*
* 1. 从哈希中提取盐值和成本因子
* 2. 使用相同的盐值和成本因子重新计算哈希
* 3. 比较结果
*/
return password_verify($plainPassword, $hashedPassword);
}
详细验证步骤
// 1. 提取哈希中的盐值 $hash = '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi'; $salt = substr($hash, 0, 29); // 包含算法、成本因子和盐值 // 2. 使用相同参数重新哈希 $newHash = crypt($plainPassword, $salt); // 3. 比较结果 $isValid = hash_equals($newHash, $hash);
Laravel 认证流程完整示例
// LoginController.php
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use App\Models\User;
class LoginController extends Controller
{
/**
* 处理登录请求
*/
public function login(Request $request)
{
$credentials = $request->validate([
'email' => ['required', 'email'],
'password' => ['required'],
]);
// 认证过程
if (Auth::attempt($credentials, $request->boolean('remember'))) {
// 认证成功
$request->session()->regenerate();
// 获取当前用户
$user = Auth::user();
// 验证用户状态
if (!$user->is_active) {
Auth::logout();
return back()->withErrors([
'email' => '账号已被禁用',
]);
}
return redirect()->intended('dashboard');
}
// 认证失败
return back()->withErrors([
'email' => '提供的凭证与记录不匹配',
])->onlyInput('email');
}
}
自定义验证逻辑
<?php
namespace App\Services;
use Illuminate\Support\Facades\Hash;
use Illuminate\Validation\ValidationException;
class AuthenticationService
{
/**
* 自定义密码验证
*/
public function authenticateUser(array $credentials): array
{
$user = User::where('email', $credentials['email'])->first();
// 用户存在且密码验证通过
if (!$user || !Hash::check($credentials['password'], $user->password)) {
return ['success' => false, 'message' => '无效的登录凭据'];
}
// 检查额外条件
if (!$user->is_active) {
return ['success' => false, 'message' => '账号已停用'];
}
// 记录最近登录时间
$user->update([
'last_login_at' => now(),
'last_login_ip' => request()->ip(),
]);
// 更新密码哈希(如果成本因子改变)
if (Hash::needsRehash($user->password)) {
$user->update([
'password' => Hash::make($credentials['password'])
]);
}
return ['success' => true, 'user' => $user];
}
}
安全检查建议
// 密码强度验证
public function validatePasswordStrength($password) {
// 至少8个字符
if (strlen($password) < 8) {
return false;
}
// 包含字母、数字、特殊字符
if (!preg_match('/[A-Z]/', $password) ||
!preg_match('/[a-z]/', $password) ||
!preg_match('/[0-9]/', $password) ||
!preg_match('/[^A-Za-z0-9]/', $password)) {
return false;
}
return true;
}
// 防暴力破解
public function throttleLoginAttempts(Request $request) {
$key = 'login_attempts:' . $request->ip();
$attempts = Cache::get($key, 0);
$attempts++;
Cache::put($key, $attempts, now()->addMinutes(15));
if ($attempts > 5) {
abort(429, '尝试次数过多,请稍后再试');
}
}
配置选项
在config/hashing.php中配置:
// config/hashing.php
return [
'driver' => 'bcrypt',
'bcrypt' => [
'rounds' => env('BCRYPT_ROUNDS', 10),
'verify' => false, // 是否需要验证算法
],
'argon' => [
'memory' => 1024,
'threads' => 2,
'time' => 2,
'verify' => false,
],
];
验证和重哈希
// 登录时检查是否需要重新哈希
public function checkAndRehash($user, $plainPassword) {
if (Hash::needsRehash($user->password)) {
// 重新计算哈希
$user->forceFill([
'password' => Hash::make($plainPassword),
])->save();
}
}
安全性最佳实践
// 使用安全的登录流程
use Illuminate\Foundation\Auth\AuthenticatesUsers;
class LoginController extends Controller
{
use AuthenticatesUsers;
// 登录尝试次数限制
protected $maxAttempts = 5;
// 锁定时间(分钟)
protected $decayMinutes = 15;
// 登录失败后的处理
protected function sendFailedLoginResponse(Request $request)
{
throw ValidationException::withMessages([
$this->username() => [trans('auth.failed')],
]);
}
}
验证核心要点:
- Bcrypt 哈希包含盐值,相同密码会产生不同哈希
- 验证时使用
password_verify()函数 - 使用
hash_equals()进行时间安全的字符串比较 - 建议定期更新密码哈希的成本因子
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播