# 前言
學習一個框架, Ray 的想法是, 在深入理解底層實作的原理之前, 應該先知道這個框架的 使用方法
; 先學習怎麼使用這個前人造的輪子, 再學習怎麼樣造一個輪子。
所以本篇文章重點在於細讀官方文件, 並將內容理解後以 Q&A 的方式記錄下來, 加速學習以及查詢。
# Gates
# Writing Gates
Laravel Authentication 中, 主要有哪兩種 authorization 方式?
gates and policies
以下的 Laravel example code 的意思是?
- Example:
<?php
public function boot()
{
$this->registerPolicies();
Gate::define('edit-settings', function ($user) {
return $user->isAdmin;
});
} - Answer:
在 AuthServiceProvider 的 boot() 當中, 使用 Gate::define 定義一個名為'edit-settings'
的 closure gate
以下的 Laravel example code 的意思是?
- Example:
<?php
public function boot()
{
$this->registerPolicies();
Gate::define('update-post', 'class@method');
} - Answer:
在定義一個 Gate closure based rule 時, 也可以選擇由指定的 class@method 來執行驗證邏輯
# Authorizing Actions
Laravel Authentication 中, 當我使用 Gate 時, 需要帶入 current $user 嗎?
不需要
以下的 Laravel example code 的意思是?
- Example:
<?php
if (Gate::allows('update-post', $post)) {
// The current user can update the post...
} - Answer:
判斷當前 authenticated user 是否被允許
update $post, 會調用該'update-post'
closure gate
以下的 Laravel example code 的意思是?
- Example:
<?php
if (Gate::denies('update-post', $post)) {
// The current user can't update the post...
} - Answer:
判斷當前 authenticated user 是否不被允許
update $post, 會 closure gateupdate-post
的驗證邏輯
以下的 Laravel example code 的意思是?
- Example:
<?php
if (Gate::forUser($user)->allows('update-post', $post)) {
// The user can update the post...
} - Answer:
判斷$user
是否被允許
update $post, 會執行update-post
這個 closure gate
以下的 Laravel example code 的意思是?
- Example:
<?php
if (Gate::any(['update-post', 'delete-post'], $post)) {
// The user can update or delete the post
} - Answer:
判斷當前 authenticated user 是否被允許
update $post 或 delete $post, 會執行update-post
以及delete-post
這兩個 closure gate
以下的 Laravel example code 的意思是?
- Example:
<?php
if (Gate::none(['update-post', 'delete-post'], $post)) {
// The user cannot update or delete the post
} - Answer:
判斷當前 authenticated user 是否皆不被允許
update $post 以及 delete $post, 會執行 update-post 以及 delete-post closure gate
# Authorizing Or Throwing Exceptions
以下的 Laravel example code 的意思是?
- Example:
<?php
Gate::authorize('update-post', $post);
// The action is authorized... - Answer:
當 current authenticated user 不具有 update-post 的權限時, throw 403 exception
以下的 Laravel example code 的意思是?
- Example:
<?php
if (Gate::check('create-post', [$category, $extraFlag])) {
// The user can create the post...
} - Answer:
判斷當前 authenticated user 是否被允許
create posts, 可使用 array 帶入複數的 parameters
# Gate Responses
以下的 Laravel example code 的意思是?
- Example:
<?php
use Illuminate\Auth\Access\Response;
use Illuminate\Support\Facades\Gate;
Gate::define('edit-settings', function ($user) {
return $user->isAdmin
? Response::allow()
: Response::deny('You must be a super administrator.');
}); - Answer:
定義一個名為 ‘edit-settings’ 的 gate, 套用後, 如果 $user 為 admin 就允許, 如果不是則 deny 並 return deny message
以下的 Laravel example code 的意思是?
- Example:
<?php
$response = Gate::inspect('edit-settings', $post);
if ($response->allowed()) {
// The action is authorized...
} else {
echo $response->message();
} - Answer:
取得 Gate 回傳的完整 authorization response
# Intercepting Gate Checks
以下的 Laravel example code 的意思是?
- Example:
<?php
Gate::before(function ($user, $ability) {
if ($user->isSuperAdmin()) {
return true;
}
}); - Answer:
訂一個規則, 會在執行所有 Gate rule 之前先執行它, 比如說我要讓 superAdmin 有所有的權限
以下的 Laravel example code 的意思是?
- Example:
<?php
Gate::after(function ($user, $ability, $result, $arguments) {
if ($user->isSuperAdmin()) {
return true;
}
}); - Answer:
會在所有的 gate rule 執行完畢後, 才會執行 after 內定義的規則, 比如說, 我要先驗證一些必要驗證, 最後在驗證該使用者是否為 admin
# Creating Policies
# Generating Policies
Laravel Authentication 中, 使用 CLI 建立的 policy 會位於哪裡?
app/Policies
資料夾
以下的 Laravel example command 的意思是?
- Example:
php artisan make:policy PolicyName --model=ModelName
- Answer:
使用 CLI 建立一個 policy 並且指定 model
# Registering Policies
Laravel Authentication 中, 當我建立了 policy 之後, 我需要在哪一個檔案中註冊它
AuthServiceProvider.php
以下的 Laravel example code 的意思是?
- Example:
<?php
namespace App\Providers;
use App\Policies\PostPolicy;
use App\Post;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Gate;
class AuthServiceProvider extends ServiceProvider
{
protected $policies = [
Post::class => PostPolicy::class,
];
public function boot()
{
$this->registerPolicies();
//
}
} - Answer:
在 AuthServiceProvider 的 policies property 中給 model 註冊 policy
# Policy Auto-Discovery
Laravel Authentication 中, 如果我不想要每次都手動註冊 policy, 我想要使用 Laravel 預設的 auto-discovery, 假設 model name 為 User, 那該 Policy name 須為?
UserPolicy
以下的 Laravel example code 的意思是?
- Example:
<?php
use Illuminate\Support\Facades\Gate;
Gate::guessPolicyNamesUsing(function ($modelClass) {
// return policy class name...
}); - Answer:
Laravel 預設的 auto-discovery 的 convention 為 modelNamePolicyName, 假如 model 為 User, 那符合 auto-discovery 的命名規則為UserPolicy
可在AuthServiceProvider
的boot()
, 使用Gate::guessPolicyNamesUsing
method 變更預設的 convention
Laravel Authentication 中, 當我同時使用手動註冊 policy 以及 auto-discovery policy 時, 哪一個的優先順序較高?
手動註冊
# Writing Policies
# Policy Methods
以下的 Laravel example code 的意思是?
- Example:
<?php
namespace App\Policies;
use App\Post;
use App\User;
class PostPolicy
{
public function update(User $user, Post $post)
{
return $user->id === $post->user_id;
}
} - Answer:
定義 PostPolicy 的 update method, 定義 user 是否有 update 該 post 的權限
以下的 Laravel example code 的意思是?
- Example:
<?php
namespace App\Policies;
use App\Post;
use App\User;
class PostPolicy
{
public function update(User $user, Post $post)
{
return $user->id === $post->user_id;
}
} - Answer:
在 PostPolicy class, update method 中定義 $user 是否被允許 update $post
# Policy Responses
以下的 Laravel example code 的意思是?
- Example:
<?php
use Illuminate\Auth\Access\Response;
public function update(User $user, Post $post)
{
return $user->id === $post->user_id
? Response::allow()
: Response::deny('You do not own this post.');
} - Answer:
<?php
// 在 policy class 中, 定義 允許, 不被允許 的 response
use Illuminate\Auth\Access\Response;
public function update(User $user, Post $post)
{
return $user->id === $post->user_id
// 允許則回覆 boolean true
? Response::allow()
// 不允許則回傳 403, message
: Response::deny('You do not own this post.');
}
Laravel Authentication 中, 根據官方文件描述, 我可以使用 Gate::inspect method 來取得 policy 的 authorization response 嗎?
可以
# Methods Without Models
以下的 Laravel example code 的意思是?
- Example:
<?php
// 在 policy class 中
public function create(User $user)
{
//
} - Answer:
由於 create() 並不需要 model parameter, 因此使用 User $user 即可
# Guest Users
Laravel Authentication 中, 預設在 policy 以及 gate 如果沒有初始化一個 authenticated user 的話, authorization 會 return 什麼?
false
Laravel Authentication 中, 預設在 policy 以及 gate 如果沒有初始化一個 authenticated user 的話, 會 return false, 如果我想要讓沒有 authenticated user 也可以通過 authorization check 的話, 有哪兩種方式??
- optional type hint
- return null
# Policy Filters
以下的 Laravel example code 的意思是?
- Example:
<?php
public function before($user, $ability)
{
return false;
} - Answer:
在執行所有 policy 之前會先執行 before, 換言之, 以上的 example 總是會 return false, 代表任何 policy 都不可能會驗證通過
比方說, 如果原本$user->can('show', $post)
是 true, 加上上面的 example 之後, 就會 return false
Laravel Authentication 中, 當我在 policy 中定義一個 before method 時, 如果該 policy class 中沒有任何 method 被呼叫, 那 before method 會被呼叫嗎?
不會哦
# Authorizing Actions Using Polices
# Via The User Model
以下的 Laravel example code 的意思是?
- Example:
<?php
if ($user->can('update', $post)) {
//
} - Answer:
使用 can() 判斷 $user 是否有 update $post 的權限, 會調用 PostPolicy
Laravel Authentication 中, 當我使用 can method 如下 example 時, 如果說我並沒有註冊這個 policy, 那 Laravel 會怎麼做?
尋找 closure based Gate
# Actions That Don’t Require Models
以下的 Laravel example code 的意思是?
- Example:
<?php
use App\Post;
if ($user->can('create', Post::class)) {
// Executes the "create" method on the relevant policy...
} - Answer:
使用 can() 驗證 $user 是否可以在 Post model 中, 有 create 的權限, 如果是 update 類型的 method 會需要帶入指定的 $model, 因為 create 是不需要帶入指定的 $model 的, 所以帶入 Post model 的完整 class name 即可
# Via Middleware
以下的 Laravel example code 的意思是?
- Example:
<?php
use App\Post;
Route::put('/post/{post}', function (Post $post) {
// The current user may update the post...
})->middleware('can:update,post'); - Answer:
使用 can middleware 驗證發 request 的 user 是否具有 update 該 post model 的權限, 第一個 arg 為 update 權限, 會執行 post policy 的 update method, 第二個 ‘post’ 為 url parameter 中帶入的該 post model, update method 會判斷該 user 是否有權限 update 該 post model
# Actions That Don’t Require Models
以下的 Laravel example code 的意思是?
- Example:
<?php
Route::post('/post', function () {
// The current user may create posts...
})->middleware('can:create,App\Post'); - Answer:
使用 can middleware 驗證 $user 是否可以在 Post model 中, 有 create 的權限, 如果是 update 類型的 method 會需要帶入指定的 $model, 因為 create 是不需要帶入指定的 $model 的, 所以帶入 Post model 的完整 class name 即可
# Via Controller Helpers
以下的 Laravel example code 的意思是?
- Example:
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use App\Post;
use Illuminate\Http\Request;
class PostController extends Controller
{
public function update(Request $request, Post $post)
{
$this->authorize('update', $post);
// The current user can update the blog post...
}
} - Answer:
使用 authorize method, 會根據定義的 policy 判斷該 authenticated user 是否有 update 該 $post 的權限, 如果不允許, 會 throw 403
# Action That Don’t Require Models
以下的 Laravel example code 的意思是?
- Example:
<?php
public function create(Request $request)
{
$this->authorize('create', Post::class);
// The current user can create blog posts...
} - Answer:
使用 authorize(), 驗證 authenticated user 是否可以在 Post model 有 create 的操作權限, 該邏輯判斷定義在 PostPolicy, 若不可會直接 throw 403
# Authorizing Resource Controllers
以下的 Laravel example code 的意思是?
- Example:
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use App\Post;
use Illuminate\Http\Request;
class PostController extends Controller
{
public function __construct()
{
$this->authorizeResource(Post::class, 'post');
}
} - Answer:
在 controller 的 construct() 中使用 authorizeResource(), arg1 為 policy model class name, arg2 為 url parameter $post, 會自動將 authorize 套用到該 Resource Controller 中的每個 method
# Via Blade Templates
以下的 Laravel example code 的意思是?
- Example:
<?php
@can('update', $post)
<!-- The Current User Can Update The Post -->
@elsecan('create', App\Post::class)
<!-- The Current User Can Create New Post -->
@endcan - Answer:
在 Blade 中判斷 current user 是否被允許
update 該 $post 的權限, 驗證邏輯定義在 PostPolicy class
以下的 Laravel example code 的意思是?
- Example:
<?php
@cannot('update', $post)
<!-- The Current User Cannot Update The Post -->
@elsecannot('create', App\Post::class)
<!-- The Current User Cannot Create A New Post -->
@endcannot - Answer:
在 Blade 中判斷 current user 是否不被允許
update 該 $post 的權限, 是否不被允許
在 Post model 執行 ‘create’ 的操作, 驗證邏輯定義在 PostPolicy class
Laravel Authentication 中, 以下的 blade template example 實際上是什麼的縮寫?
- Example:
<?php
@can('update', $post)
<!-- The Current User Can Update The Post -->
@endcan
@cannot('update', $post)
<!-- The Current User Cannot Update The Post -->
@endcannot - Answer:
<?php
@if (Auth::user()->can('update', $post))
<!-- The Current User Can Update The Post -->
@endif
@unless (Auth::user()->can('update', $post))
<!-- The Current User Cannot Update The Post -->
@endunless
以下的 Laravel example code 的意思是?
- Example:
<?php
@canany(['update', 'view', 'delete'], $post)
// The current user can update, view, or delete the post
@elsecanany(['create'], \App\Post::class)
// The current user can create a post
@endcanany - Answer:
判斷 current user 是否被允許
update 或 view 或 delete $post model, 任意一項都算
判斷 current user 是否被允許
在 Post model 中實施create
的操作
以上的權限邏輯都定義在 PostPolicy
# Actions That Don’t Require Models
以下的 Laravel example code 的意思是?
- Example:
<?php
@can('create', App\Post::class)
<!-- The Current User Can Create Posts -->
@endcan
@cannot('create', App\Post::class)
<!-- The Current User Can't Create Posts -->
@endcannot - Answer:
使用 Blade authorization method
判斷 current user 是否被允許
對 Post model 操作 create 的權限
判斷 current user 是否不被允許
對 Post model 操作 create 的權限
驗證邏輯會使用定義好的 policy
# Supplying Additional Context
Laravel Authentication 中, 在定義 policy 時, 如果除了 user 以及 model 之外, 我還要帶入額外的參數來驗證, 在以下的 example 中, 參數可以帶在哪?
- Example:
<?php
public function update(User $user, Post $post, int $category)
{
return $user->id === $post->user_id &&
$category > 3;
} - Answer:
定義 PostPolicy, 若有需要可帶入多個 args
以下的 Laravel example code 的意思是?
- Example:
<?php
public function update(Request $request, Post $post)
{
$this->authorize('update', [$post, $request->input('category')]);
// The current user can update the blog post...
} - Answer:
在 controller 的 update method 中, 使用 authorize() 來驗證 authenticated user 是否有 update 該 $post 的權限, 帶入兩個參數, 這兩個參數會被 pass 到 policy 或 closure based gate
留言