Laravel Authorization
Laravel 提供兩種主要的 authorizing action:gate 跟 policy
可以把 gates 跟 policies 想像成 routes 跟 controllers。
Gates are most applicable to actions which are not related to any model or resource, such as viewing an administrator dashboard. In contrast, policies should be used when you wish to authorize an action for a particular model or resource.
通常 gates 跟 policies 會混合使用。
Gates
Gates are simply closures that determine if a user is authorized to perform a given action.
gates 通常定義在 App\Providers\AuthServiceProvider::boot()
,用 Gate
facade 來定義:
1 | public function boot() |
也可以用 class callback 形式:
1 | Gate::define('update-post', [PostPolicy::class, 'update']); |
定義 gate 後,要在需要擋權限的地方(例如 controller action)使用 Gate::allows()
或 Gate::denies()
:
1 | class PostController extends Controller |
不用自己丟目前登入的 user instance 進去,laravel 會 handle 這件事。
如果不是要看現在登入的 user,而是要 authorize 另外的 user,可以使用 forUser()
:
1 | if (Gate::forUser($user)->allows('update-post', $post)) { |
可以用 any()
跟 none()
來同時 authorize 多個 action:
1 | if (Gate::any(['update-post', 'delete-post'], $post)) { |
如果想要在 authorize 失敗的時候自動丟 Illuminate\Auth\Access\AuthorizationException
:
1 | Gate::authorize('update-post', $post); |
Illuminate\Auth\Access\AuthorizationException
會自動被轉成 403 response by Laravel’s exception handler。
可以 support 複雜的 context:https://laravel.com/docs/8.x/authorization#gates-supplying-additional-context
Gate define 的時候也可以 return Illuminate\Auth\Access\Response
來帶更多資訊。Ref
如果想要讓某個 user 可以 grant all ability,可以用 before()
Ref:
1 | Gate::before(function ($user, $ability) { |
If the
before
closure returns a non-null result that result will be considered the result of the authorization check.
也可以用 after
來定義在所有 authorization check 執行後執行的 closure。
Policies
Policies are classes that organize authorization logic around a particular model or resource.
可以用 make:policy
來產生 policy class,產生的 policy 會放在 app/Policies/
。
如果想要有跟某個 model 關聯的 example policy:
1 | $ php artisan make:policy PostPolicy --model=Post |
Register policy
有 policy class 後,要 register 它。
Registering policies is how we can inform Laravel which policy to use when authorizing actions against a given model type.
在 App\Providers\AuthServiceProvider
裡有個 policies
property,它的 key 是 model class,value 是對應的 policy class name。
Registering a policy will instruct Laravel which policy to utilize when authorizing actions against a given Eloquent model:
1 | class AuthServiceProvider extends ServiceProvider |
Write Policy
大致長這樣,可以寫任意 function:
1 | class PostPolicy |
如果用 --model
生,會生出 CRUD 有關的 function。
使用 Policy
透過 User Model
1 | class PostController extends Controller |
沒有 model instance 的 policy:
1 | public function store(Request $request) |
透過 Controller Helpers
1 | class PostController extends Controller |
如果是 resource controller,可以這樣:
1 | class PostController extends Controller |
要注意 CRUD 的 function 的 signature 要符合 laravel 需要的 type hint 才能用
透過 middleware
1 | Route::put('/post/{post}', function (Post $post) { |