Laravel 內建重置密碼基於「忘記密碼 → 郵件發送 Token → 郵件鏈接重置」,適用於用戶自助找回。但後台管理系統常需:已登錄用戶修改密碼、驗證舊密碼、密碼複雜度策略、修改後強制重新登錄。本文實現後台風格重置密碼。
// routes/web.php
Route::get('reset', 'UserController@getReset')->middleware('auth');
Route::post('reset', 'UserController@postReset')->middleware('auth');
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\{Auth, Hash, Validator};
class UserController extends Controller {
// 顯示重置頁面
public function getReset() {
return view('auth.reset');
}
// 處理重置提交
public function postReset(Request $request) {
// 1. 基礎驗證規則
$rules = [
'oldpassword' => 'required|between:6,20',
'password' => 'required|between:6,20|confirmed',
];
$messages = [
'required' => '密碼不能為空',
'between' => '密碼必須是 6-20 位',
'confirmed' => '新密碼與確認密碼不一致',
];
$validator = Validator::make($request->all(), $rules, $messages);
// 2. 自定義驗證:舊密碼正確性
$user = Auth::user();
$validator->after(function ($validator) use ($request, $user) {
if (!Hash::check($request->input('oldpassword'), $user->password)) {
$validator->errors()->add('oldpassword', '原密碼錯誤');
}
});
if ($validator->fails()) {
return back()->withErrors($validator)->withInput();
}
// 3. 更新密碼
$user->password = bcrypt($request->input('password'));
$user->save();
// 4. 安全:強制登出,要求重新登錄
Auth::logout();
return redirect('/login')->with('success', '密碼修改成功,請重新登錄');
}
}
| 技術點 | 實現方式 | 作用 |
|---|---|---|
| confirmed 規則 | password_confirmation 欄位自動匹配 | 前端只需添加確認輸入框 |
| after 回調 | $validator->after(fn() => ...) | 在所有規則通過後執行業務邏輯驗證 |
| use 閉包傳參 | use ($request, $user) | 將外部變量引入匿名函數作用域 |
| 全局命名空間 | \Hash::check() | 控制器在 App\Http\Controllers 命名空間下 |
| 錯誤定位顯示 | @error('field') Blade 指令 | 字段級錯誤提示,體驗更好 |
| 修改後登出 | Auth::logout() | 防止舊 Session 被盜用,安全最佳實踐 |
// App\Rules\StrongPassword.php
namespace App\Rules;
use Illuminate\Contracts\Validation\Rule;
class StrongPassword implements Rule {
public function passes($attribute, $value) {
// 至少 1 大寫、1 小寫、1 數字、1 特殊字符、8 位以上
return preg_match('/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$/', $value);
}
public function message() {
return '密碼需包含大小寫、數字、特殊字符,長度 8 位以上';
}
}
// 控制器中使用
'rules' => [
'password' => ['required', new StrongPassword, 'confirmed'],
],
路由已掛載 middleware('auth'),內核已註冊 \App\Http\Middleware\Authenticate::class。未登錄用戶自動重定向至 /login。
重置密碼看似簡單,實則涉及 驗證鏈、密碼哈希、會話安全、用戶體驗 多個維度。Laravel 的 Validator + after() + Hash 組合極其優雅地解決了「舊密碼驗證」這一非標準規則。建議將此模式封裝為 ChangePasswordRequest Form Request 類,控制器僅保留 $request->validated() 與業務邏輯,進一步精簡代碼。