# Laravel Policy 可用在`用戶只能編輯自己的資料`,當 id 為 2 的用戶去嘗試更新 id 為 1 的用戶資訊時,返回一個 403 禁止訪問的異常。 `$ php artisan make:policy UserPolicy` *app/Policies/UserPolicy.php* ```php= <?php namespace App\Policies; use Illuminate\Auth\Access\HandlesAuthorization; use App\Models\User; class UserPolicy { use HandlesAuthorization; public function update(User $currentUser, User $user) { return $currentUser->id === $user->id; } } ``` **自動授權註冊** *app\Providers\AuthServiceProvider.php* ```php= <?php namespace App\Providers; . . . class AuthServiceProvider extends ServiceProvider { . . . public function boot() { $this->registerPolicies(); // 修改策略自動發現的邏輯 Gate::guessPolicyNamesUsing(function ($modelClass) { // 動態返回模型對應的策略名稱,如:// 'App\Models\User' => 'App\Policies\UserPolicy', return 'App\Policies\\'.class_basename($modelClass).'Policy'; }); } } ``` `App\Http\Controllers\Controller` 類別包含了 Laravel 的 `AuthorizesRequests` trait,此 trait 提供了 `Authorize` 方法,它可以被用於快速授權一個指定的行為,當無權限運行該行為時會拋出 HttpException。`authorize` 方法接收兩個參數,第一個為授權策略的名稱,第二個為進行授權驗證的資料。 `$this->authorize('update', $user);` *app\Http\Controllers\UsersController.php* ```php= <?php namespace App\Http\Controllers; . . . class UsersController extends Controller { . . . public function edit(User $user) { $this->authorize('update', $user); return view('users.edit', compact('user')); } public function update(User $user, Request $request) { $this->authorize('update', $user); $this->validate($request, [ 'name' => 'required|max:50', 'password' => 'nullable|confirmed|min:6' ]); $data = []; $data['name'] = $request->name; if ($request->password) { $data['password'] = bcrypt($request->password); } $user->update($data); session()->flash('success', '個人資料更新成功!'); return redirect()->route('users.show', $user); } } ``` 現在,使用 id 為 2 的用戶登入,當訪問 id 為 1 的用戶編輯頁面,系統將會拒絕訪問。 ![](https://i.imgur.com/Eygzl6z.png) ### 友善的登入重新導向 當一個未登入的用戶嘗試訪問自己的資料編輯頁面時,將會自動跳轉到登入頁面,這時候如果用戶再進行登入,則會重新導向到其個人中心頁面上,這種方式的用戶體驗並不好,更好的做法是,將用戶重新導向到他之前嘗試訪問的頁面,即自己的資料編輯頁面。redirect() 實例提供了一個 `intended` 方法,該方法可將頁面重新導向到上一次請求嘗試訪問的頁面上,並接收一個預設轉跳地址參數,當上一次請求記錄為空時,跳轉到預設地址上。 *app/Http/Controllers/SessionsController.php* ```php= <?php namespace App\Http\Controllers; . . . class SessionsController extends Controller { . . . public function store(Request $request) { $credentials = $this->validate($request, [ 'email' => 'required|email|max:255', 'password' => 'required' ]); if (Auth::attempt($credentials, $request->has('remember'))) { session()->flash('success', '歡迎回來!'); $fallback = route('users.show', Auth::user()); return redirect()->intended($fallback); } else { session()->flash('danger', '很抱歉,您的信箱或密碼輸入錯誤!'); return redirect()->back()->withInput(); } } . . . } ``` 現在嘗試退出登入,並訪問 /users/1/edit 頁面,頁面將重新導向到登入頁面,這時候接著使用 id 為 1 的用戶進行登入,在登入成功後頁面將重新導向到用戶編輯頁面上。 ![](https://i.imgur.com/OFW2Cjd.png) ###### tags: `Laravel`