# 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 的用戶編輯頁面,系統將會拒絕訪問。

### 友善的登入重新導向
當一個未登入的用戶嘗試訪問自己的資料編輯頁面時,將會自動跳轉到登入頁面,這時候如果用戶再進行登入,則會重新導向到其個人中心頁面上,這種方式的用戶體驗並不好,更好的做法是,將用戶重新導向到他之前嘗試訪問的頁面,即自己的資料編輯頁面。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 的用戶進行登入,在登入成功後頁面將重新導向到用戶編輯頁面上。

###### tags: `Laravel`