Laravel - Security - Authorization

# 前言

學習一個框架, Ray 的想法是, 在深入理解底層實作的原理之前, 應該先知道這個框架的 使用方法; 先學習怎麼使用這個前人造的輪子, 再學習怎麼樣一個輪子。
所以本篇文章重點在於細讀官方文件, 並將內容理解後以 Q&A 的方式記錄下來, 加速學習以及查詢。

# Gates

# Writing Gates

Laravel Authentication 中, 主要有哪兩種 authorization 方式?

gates and policies

Laravel Authentication 中, 如果我要定義一個 closure 來限制 authorization, 在以下的 example 中, 該使用哪個 class?
  • Example:

    <?php
    public function boot()
    {
    $this->registerPolicies();

    這裡是?::define('edit-settings', function ($user) {
    return $user->isAdmin;
    });
    }
  • Answer:

    <?php
    public function boot()
    {
    $this->registerPolicies();

    Gate::define('edit-settings', function ($user) {
    return $user->isAdmin;
    });
    }
Laravel Authentication 中, 如果我要定義一個 closure 來限制 authorization, 在以下的 example 中, 該使用哪個 method?
  • Example:

    <?php
    public function boot()
    {
    $this->registerPolicies();

    Gate::這裡是?('edit-settings', function ($user) {
    return $user->isAdmin;
    });
    }
  • Answer:

    <?php
    public function boot()
    {
    $this->registerPolicies();

    Gate::define('edit-settings', function ($user) {
    return $user->isAdmin;
    });
    }
Laravel Authentication 中, 如果我要定義一個 closure 來限制 authorization, 在以下的 example 中, closure 的預設第一個 argument 是?
  • Example:

    <?php
    public function boot()
    {
    $this->registerPolicies();

    Gate::define('edit-settings', function (這裡是?) {
    return $user->isAdmin;
    });
    }
  • Answer:

    <?php
    public function boot()
    {
    $this->registerPolicies();

    Gate::define('edit-settings', function ($user) {
    return $user->isAdmin;
    });
    }
Laravel Authentication 中, 以下的 Gate define example, 除了使用 closure 之外還可以使用什麼其他的方式?
  • Example:

    <?php
    public function boot()
    {
    $this->registerPolicies();

    Gate::define('update-post', 這裡是?);
    }
  • Answer:

    <?php
    public function boot()
    {
    $this->registerPolicies();

    Gate::define('update-post', 'class@method');
    }


# Authorizing Actions

Laravel Authentication 中, 當我使用 Gate 時, 需要帶入 current $user 嗎?

不需要

Laravel Authentication 中, 如果我的情境是, 假如目前使用者可以更新 post, 我要在 conditional block 中做一些事, 那在以下的 example 中, 該使用哪一個 method?
  • Example:

    <?php
    if (Gate::這裡是?('update-post', $post)) {
    // The current user can update the post...
    }
  • Answer:

    <?php
    if (Gate::allows('update-post', $post)) {
    // The current user can update the post...
    }
Laravel Authentication 中, 如果我的情境是, 假如目前使用者沒有更新 post 的權限, 我要在 conditional block 中做一些事, 那在以下的 example 中, 該使用哪一個 method?
  • Example:

    <?php
    if (Gate::這裡是?('update-post', $post)) {
    // The current user can't update the post...
    }
  • Answer:

    <?php
    if (Gate::denies('update-post', $post)) {
    // The current user can't update the post...
    }
Laravel Authentication 中, 如果我的情境是, 假如使用者 $user 可以更新 post, 我要在 conditional block 中做一些事, 那在以下的 example 中, 該使用哪一個 method?
  • Example:

    <?php
    if (Gate::這裡是?($user)->allows('update-post', $post)) {
    // The user can update the post...
    }
  • Answer:

    <?php
    if (Gate::forUser($user)->allows('update-post', $post)) {
    // The user can update the post...
    }
Laravel Authentication 中, 假如我的使用情境是, 如果目前使用者具有 ‘update-post’ 或 ‘delete-post’ 權限之一, 那我就要在 conditional block 中做一些事, 在以下的 example 中, 該使用哪個 method?
  • Example:

    <?php
    if (Gate::這裡是?(['update-post', 'delete-post'], $post)) {
    // The user can update or delete the post
    }
  • Answer:

    <?php
    if (Gate::any(['update-post', 'delete-post'], $post)) {
    // The user can update or delete the post
    }
Laravel Authentication 中, 假如我的使用情境是, 如果目前使用者不具有 ‘update-post’ 權限, 也不具有 ‘delete-post’ 權限, 那我就要在 conditional block 中做一些事, 在以下的 example 中, 該使用哪個 method?
  • Example:

    <?php
    if (Gate::這裡是?(['update-post', 'delete-post'], $post)) {
    // The user cannot update or delete the post
    }
  • Answer:

    <?php
    if (Gate::none(['update-post', 'delete-post'], $post)) {
    // The user cannot update or delete the post
    }


# Authorizing Or Throwing Exceptions

Laravel Authentication 中, 如果情境是, 當前使用者如果不具有 update-post 權限時, 就 throw 403 exception, 那在以下 example 中, 該使用哪個 method?
  • Example:

    <?php
    Gate::這裡是?('update-post', $post);

    // The action is authorized...
  • Answer:

    <?php
    Gate::authorize('update-post', $post);

    // The action is authorized...
Laravel Authentication 中, 如果我要使用以下的 Gate definition, 那在以下的 example use case 中, 該帶入什麼 arguments?
  • Gate Definition:

    <?php
    Gate::define('create-post', function ($user, $category, $extraFlag) {
    return $category->group > 3 && $extraFlag === true;
    });
  • Use Case:

    <?php
    if (Gate::check('create-post', 這裡是?)) {
    // The user can create the post...
    }
  • Answer:

    <?php
    if (Gate::check('create-post', [$category, $extraFlag])) {
    // The user can create the post...
    }


# 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

Laravel Authentication 中, 在以下的 example, 該怎麼做?
  • Example:

    <?php
    $response = Gate::inspect('edit-settings', $post);

    if ($response->這裡是?()) {
    // The action is authorized...
    } else {
    // 印出 denied 訊息
    echo $response->這裡是?();
    }
  • Answer:

    <?php
    $response = Gate::inspect('edit-settings', $post);

    if ($response->allowed()) {
    // The action is authorized...
    } else {
    // 印出 denied 訊息
    echo $response->message();
    }


# 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, 可以怎麼做?
php artisan make:policy PolicyName
Laravel Authentication 中, 使用 CLI 建立的 policy 會位於哪裡?

app/Policies 資料夾

Laravel Authentication 中, 如果我要使用 CLI 來建立一個 policy, 並且指定 model, 可以怎麼做?
php artisan make:policy PolicyName --model=ModelName

# 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 Authentication 中, 當我使用 auto-discovery 時, 如果我想要自定義 discover 的規則, 在以下的 example 中, 是在哪個檔案的哪個 method?
  • Example:

    <?php
    // 這裡是哪個檔案哪個 method?
    use Illuminate\Support\Facades\Gate;

    Gate::guessPolicyNamesUsing(function ($modelClass) {
    // return policy class name...
    });
  • Answer:

    • AuthServiceProvider
    • boot
以下的 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
    guessPolicyNamesUsing method 可以變更預設的 convention

Laravel Authentication 中, 當我同時使用手動註冊 policy 以及 auto-discovery policy 時, 哪一個的優先順序較高?

手動註冊




# Writing Policies

# Policy Methods

Laravel Authentication 中, 如果我要定義該 user 是否有權限 update Post model, 在以下的 example 中, 該使用哪個 method?
  • Example:

    <?php

    namespace App\Policies;

    use App\Post;
    use App\User;

    class PostPolicy
    {
    public function 這裡是?(User $user, Post $post)
    {
    return $user->id === $post->user_id;
    }
    }
  • Answer:

    <?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;
    }
    }
Laravel Authentication 中, 如果我要定義該 user 是否有權限 update Post model, 在以下的 example 中, 該帶入什麼 argument?
  • Example:

    <?php

    namespace App\Policies;

    use App\Post;
    use App\User;

    class PostPolicy
    {
    public function update(這裡是?)
    {
    return $user->id === $post->user_id;
    }
    }
  • Answer:

    <?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;
    }
    }


# Policy Responses

Laravel Authentication 中, 在以下的 policy example, 如果我要定義 authorization 的 return 結果, 該使用什麼 method?
  • Example:

    <?php
    use Illuminate\Auth\Access\Response;

    public function update(User $user, Post $post)
    {
    return $user->id === $post->user_id
    ? Response::這裡是?()
    : Response::這裡是?('You do not own this post.');
    }
  • Answer:

    <?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.');
    }
Laravel Authentication 中, 在以下的 policy example, allow() method 會 return 什麼?
  • Example:

    <?php
    use Illuminate\Auth\Access\Response;

    public function update(User $user, Post $post)
    {
    return $user->id === $post->user_id
    // 這邊的 allow() 會 return?
    ? Response::allow()
    : Response::deny('You do not own this post.');
    }
  • Answer:
    boolean true

Laravel Authentication 中, 根據官方文件描述, 我可以使用 Gate::inspect method 來取得 policy 的 authorization response 嗎?

可以


# Methods Without Models

Laravel Authentication 中, policy 的某些 method 可能不會接收該 model 的 instance, 像是 create method, 在以下的 example 中, 該 method 會接收什麼 argument?
  • Example:

    <?php
    /**
    * Determine if the given user can create posts.
    *
    * @param \App\User $user
    * @return bool
    */
    public function create(這裡是?)
    {
    //
    }
  • Answer:

    <?php
    /**
    * Determine if the given user can create posts.
    *
    * @param \App\User $user
    * @return bool
    */
    public function create(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 Authentication 中, 如果我要在 policy 中定義一個 method, 該 method 將會在所有的 policy 之前執行, 通常會用於給予管理者最高的權限, 那在以下的 example 中, 該使用哪一個 method?
  • Example:

    <?php
    public function 這裡是?($user, $ability)
    {
    if ($user->isSuperAdmin()) {
    return true;
    }
    }
  • Answer:

    <?php
    public function before($user, $ability)
    {
    if ($user->isSuperAdmin()) {
    return true;
    }
    }
Laravel Authentication 中, 當我在 policy 中定義 method 時, 如果我想要 deny 所有 user, 在以下的 example 中, 該 return 什麼?
  • Example:

    <?php
    public function before($user, $ability)
    {
    // 這裡是?
    }
  • Answer:

    <?php
    public function before($user, $ability)
    {
    return false;
    }
Laravel Authentication 中, 當我在 policy 中定義一個 before method 時, 如果該 policy class 中沒有任何 method 被呼叫, 那 before method 會被呼叫嗎?

不會哦




# Authorizing Actions Using Polices

# Via The User Model

Laravel Authentication 中, 當我註冊好 policy 之後, 如果我的使用情境是, 假如該 user 有 update Post model 的權限的話, 那就…, 在以下的 example 中, 該使用哪個 method?
  • Example:

    <?php
    if ($user->這裡是?('update', $post)) {
    //
    }
  • Answer:

    <?php
    if ($user->can('update', $post)) {
    //
    }
Laravel Authentication 中, 當我使用 can method 如下 example 時, 如果說我並沒有註冊這個 policy, 那 Laravel 會怎麼做?

尋找 closure based Gate


# Actions That Don’t Require Models

Laravel Authentication 中, 當使用 policy can method 時, 如果我要 authorize 的 action 是不需要帶入 model instance 的, 而我要 create 一筆 Post model 的 record, 在以下的 example 中, 該帶入什麼?
  • Example:

    <?php
    use App\Post;

    if ($user->can('create', 這裡是?)) {
    // Executes the "create" method on the relevant policy...
    }
  • Answer:

    <?php
    use App\Post;

    if ($user->can('create', Post::class)) {
    // Executes the "create" method on the relevant policy...
    }


# Via Middleware

Laravel Authentication 中, 當使用 policy 時, 如果我要使用預設的 middleware 來 authorize action, 在以下的 example 中, 該使用哪個 middleware?
  • Example:

    <?php
    use App\Post;

    Route::put('/post/{post}', function (Post $post) {
    // The current user may update the post...
    })->middleware('這裡是?:update,post');
  • Answer:

    <?php
    use App\Post;

    Route::put('/post/{post}', function (Post $post) {
    // The current user may update the post...
    })->middleware('can:update,post');
以下的 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 權限, 會執行 PostPolicy 的 update method, 第二個 ‘post’ 為 url parameter 中帶入的該 Post model, update method 會判斷該 user 是否有權限 update 該 Post model


# Actions That Don’t Require Models

Laravel Authentication 中, 當透過預設 middleware 來使用 policy 時, 如果 action 是不需要 model 的, 比如我要 create Post model record, 如下 example, 那我該帶入哪些參數?
  • Example:

    <?php
    Route::post('/post', function () {
    // The current user may create posts...
    })->middleware('can:這裡是?');
  • Answer:

    <?php
    Route::post('/post', function () {
    // The current user may create posts...
    })->middleware('can:create,App\Post');


# Via Controller Helpers

Laravel Authentication 中, 當我已經註冊好 policy, 如果我要在以下的 example 中驗證 authorization, 若不通過則直接回應 403, 該使用哪個 method?
  • 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->這裡是?('update', $post);

    // The current user can update the blog post...
    }
    }
  • Answer:

    <?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...
    }
    }


# Action That Don’t Require Models

Laravel Authentication 中, 當我使用 Controller Helpers 來驗證 policy 時, 如下 example, 如果該 policy 並不需要帶入 model, 例如 create Post model record, 那我該帶入什麼參數?
  • Example:

    <?php
    public function create(Request $request)
    {
    $this->authorize(這裡是?);

    // The current user can create blog posts...
    }
  • Answer:

    <?php
    public function create(Request $request)
    {
    $this->authorize('create', Post::class);

    // The current user can create blog posts...
    }


# Authorizing Resource Controllers

Laravel Authentication 中, 如果我要在 Resource controller 中使用 policy 話, 在以下的 example 中, 可以使用哪一個 method?
  • 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->這裡是?(Post::class, 'post');
    }
    }
  • Answer:

    <?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');
    }
    }
Laravel Authentication 中, 如果我要在 Resource controller 中使用 policy 話, 在以下的 example 中, 帶入 authorizeResource method 的兩個參數分別代表什麼?
  • 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:

    <?php

    namespace App\Http\Controllers;

    use App\Http\Controllers\Controller;
    use App\Post;
    use Illuminate\Http\Request;

    class PostController extends Controller
    {
    public function __construct()
    {
    // 第一個: 該 policy 的 model name
    // 第二個: url parameter
    $this->authorizeResource(Post::class, 'post');
    }
    }


# Via Blade Templates

Laravel Authentication 中, 在以下的 blade template example 當中, 如果我的使用情境是 假如 auth 使用者有更新 post 的權限, 我就可以做某些事, 假如 auth 使用者有建立 post 的權限, 我就可以做某些事, 那該使用哪些 method?
  • Example:

    <?php
    @這裡是?('update', $post)
    <!-- The Current User Can Update The Post -->
    @這裡是?('create', App\Post::class)
    <!-- The Current User Can Create New Post -->
    @這裡是?
  • Answer:

    <?php
    @can('update', $post)
    <!-- The Current User Can Update The Post -->
    @elsecan('create', App\Post::class)
    <!-- The Current User Can Create New Post -->
    @endcan
Laravel Authentication 中, 在以下的 blade template example 當中, 如果我的使用情境是 假如 auth 使用者沒有更新 post 的權限, 我就做某些事, 假如 auth 使用者沒有建立 post 的權限, 我就做某些事, 那該使用哪些 method?
  • Example:

    <?php
    @這裡是?('update', $post)
    <!-- The Current User Cannot Update The Post -->
    @這裡是?('create', App\Post::class)
    <!-- The Current User Cannot Create A New Post -->
    @這裡是?
  • Answer:

    <?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
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 Authentication 中, 在以下的 blade template example, 如果我的使用情境是, 假如 auth user 有 update, view, delete 其中任何一項權限, 我就做某事, 如果有 create 權限, 我就做某事, 那該使用哪些 method?
  • Example:

    <?php
    @這裡是?(['update', 'view', 'delete'], $post)
    // The current user can update, view, or delete the post
    @這裡是?(['create'], \App\Post::class)
    // The current user can create a post
    @這裡是?
  • Answer:

    <?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


# Actions That Don’t Require Models

Laravel Authentication 中, 在以下的 blade template example 當中, 如果我要驗證的權限並不需要 model instance, 那我要帶入什麼?
  • Example:

    <?php
    @can('create', 這裡是?)
    <!-- The Current User Can Create Posts -->
    @endcan

    @cannot('create', 這裡是?)
    <!-- The Current User Can't Create Posts -->
    @endcannot
  • Answer:

    <?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


# Supplying Additional Context

Laravel Authentication 中, 在定義 policy 時, 如果除了 user 以及 model 之外, 我還要帶入額外的參數來驗證, 在以下的 example 中, 參數可以帶在哪?
  • Example:

    <?php
    public function update(User $user, Post $post, 這裡是?)
    {
    return $user->id === $post->user_id &&
    $category > 3;
    }
  • Answer:

    <?php
    public function update(User $user, Post $post, int $category)
    {
    return $user->id === $post->user_id &&
    $category > 3;
    }
Laravel Authentication 中, 在以下的 Controller example 中, 如果我要帶入兩個以上的參數, 假如是 $post 以及 $request->input(‘category’), 該帶入什麼參數?
  • Example:

    <?php
    public function update(Request $request, Post $post)
    {
    $this->authorize('update', 這裡是?);

    // The current user can update the blog post...
    }
  • Answer:

    <?php
    public function update(Request $request, Post $post)
    {
    $this->authorize('update', [$post, $request->input('category')]);

    // The current user can update the blog post...
    }
Laravel - Security - Email Verification HTTP 學習筆記

留言

Your browser is out-of-date!

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

×