Laravel - Security - Authorization (官方文件原子化翻譯筆記)

# 前言

學習一個框架, 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 gate update-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 $postdelete $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
    可在 AuthServiceProviderboot(), 使用 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 是否 被允許 updateviewdelete $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
Laravel - Security - Email Verification (官方文件原子化翻譯筆記) HTTP 學習筆記

留言

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×