国产av日韩一区二区三区精品,成人性爱视频在线观看,国产,欧美,日韩,一区,www.成色av久久成人,2222eeee成人天堂

Laravel 5.8 中文文檔手冊 / 用戶授權(quán)

用戶授權(quán)

用戶授權(quán)


用戶授權(quán)

簡介

除了提供開箱即用的 用戶認(rèn)證服務(wù)外,Laravel 還提供了一種簡單的方法來處理用戶的授權(quán)動作。與用戶認(rèn)證一樣,Laravel 的授權(quán)方法很簡單,授權(quán)操作有兩種主要方式:gates 和策略。

可以把 gates 和策略比作路由和控制器。Gates 提供了一種簡單的基于閉包的授權(quán)方法,而策略和控制器類似,圍繞特定模型或資源對其邏輯進(jìn)行分組來實現(xiàn)授權(quán)認(rèn)證。我們先探索 gates,然后研究策略。

在構(gòu)建一個應(yīng)用的時候,不用在專門使用 gates 或者只使用策略之間進(jìn)行選擇。大部分應(yīng)用很可能同時包含 gates 和策略, 并且能夠很好的進(jìn)行工作。 Gates 大部分應(yīng)用在模型和資源沒有關(guān)系的地方,比如查看管理員的面板。與之相反,策略應(yīng)該在特定的模型或者資源中使用。

Gates

編寫 Gates

Gates 是用來決定用戶是否授權(quán)執(zhí)行給予動作的一個閉包函數(shù),并且典型的做法就是在
App\Providers\AuthServiceProvider 中使用 Gate 來定義.  Gates 總是接收一個用戶實例作為第一個參數(shù),并且可以接收可選參數(shù),比如相關(guān)的 Eloquent 模型:

/**
 * 注冊任意用戶認(rèn)證、用戶授權(quán)服務(wù)。
 *
 * @return void
 */
 public function boot(){ 
    $this->registerPolicies();    
    Gate::define('update-post', function ($user, $post) {  
          return $user->id == $post->user_id;  
       });
  }

Gates 也可以使用類似控制器方法 Class@method 風(fēng)格的回調(diào)字符串來定義:

/**
 * 注冊任意用戶認(rèn)證、用戶授權(quán)服務(wù)。
 *
 * @return void
 */
 public function boot(){ 
    $this->registerPolicies();    
    Gate::define('update-post', 'App\Policies\PostPolicy@update');
   }

資源 Gates

你還可以使用 resource 方法去一次性的定義多個 Gate 方法:

Gate::resource('posts', 'App\Policies\PostPolicy');

上面的手動定義和以下的 Gate 定義效果是相同的:

Gate::define('posts.view', 'App\Policies\PostPolicy@view');
Gate::define('posts.create', 'App\Policies\PostPolicy@create');
Gate::define('posts.update', 'App\Policies\PostPolicy@update');
Gate::define('posts.delete', 'App\Policies\PostPolicy@delete');

默認(rèn)情況下將會定義 view, create, update, 和 delete 方法。通過將一個數(shù)組作為第三個參數(shù)傳給  resource 方法。你可以覆蓋或者添加到默認(rèn)的方法中。數(shù)組的鍵定義能力的名稱,值定義方法的名稱。例如,下面的代碼將創(chuàng)建兩個新的 Gate 定義 -  posts.imageposts.photo:

Gate::resource('posts', 'PostPolicy', [ 
   'image' => 'updateImage',    
   'photo' => 'updatePhoto',
 ]);

授權(quán)動作

使用 gates 來授權(quán)動作的時候, 你應(yīng)該使用 allows 或者 denies 方法。 注意,不需要將當(dāng)前已認(rèn)證用戶傳遞給這些方法。 Laravel 會自動處理好已經(jīng)認(rèn)證通過的用戶,然后傳遞給 gete 閉包函數(shù):

if (Gate::allows('update-post', $post)) { 
   // 指定當(dāng)前用戶可以進(jìn)行更新...
  }
if (Gate::denies('update-post', $post)) { 
   // 指定當(dāng)前用戶不能更新...
  }

如果你想判斷一個特定的用戶是否已經(jīng)被授權(quán)訪問某個動作, 你可以使用在  Gate 在 facade 的 forUser 方法:

if (Gate::forUser($user)->allows('update-post', $post)) {
    // 用戶可以更新...
  }
if (Gate::forUser($user)->denies('update-post', $post)) {
    // 用戶不能更新...
  }

Gate 攔截檢查

有時,你可能希望將所有能力授予特定用戶。所以你可以在所有其他授權(quán)檢查之前使用 before 方法來定義運行的回調(diào):

Gate::before(function ($user, $ability) { 
   if ($user->isSuperAdmin()) {   
        return true;  
    }
});

如果 before 回調(diào)方法返回的是非 null 的結(jié)果,則結(jié)果將被視為檢查結(jié)果。

在每次授權(quán)檢查后你可以使用 after 方法定義要執(zhí)行的回調(diào)。 但是,你不能從 after 回調(diào)方法中修改授權(quán)檢查的結(jié)果:

Gate::after(function ($user, $ability, $result, $arguments) { 
   //
});

before 檢查類似,如果 after 回調(diào)返回非 null 結(jié)果,則結(jié)果將被視為檢查結(jié)果。

創(chuàng)建策略

生成策略

策略是在特定模型或者資源中組織授權(quán)邏輯的類。例如,你的應(yīng)用是一個博客,那么你在創(chuàng)建或者更新博客的時候,你可能會有一個 Post 模型和一個對應(yīng)的 PostPolicy 來授權(quán)用戶動作。

你可以使用 artisan 命令 artisan command 中的 make:policy artisan command 命令來生成策略。 生成的策略將放置在  app/Policies 目錄中。如果在你的應(yīng)用中不存在這個目錄,那么 Laravel 將會為你自動生成:

php artisan make:policy PostPolicy

make:policy 命令會生成一個空的策略類。如果你想生成的類包含基本的 「CRUD」策略方法,你可以在執(zhí)行命令的時候指定  --model 這個選項:

php artisan make:policy PostPolicy --model=Post

{tip} 所有的策略會通過 Laravel 的  服務(wù)容器,來解析,允許你在策略構(gòu)造器中對任何需要的依賴使用類型提示,并且自動注入。

注冊策略

一旦策略存在,它就需要進(jìn)行注冊。新的 Laravel 應(yīng)用中包含的 AuthServiceProvider 有一個 policies 屬性,可以將各種模型對應(yīng)到它們的策略中。注冊一個策略將引導(dǎo) Laravel 在授權(quán)動作訪問指定模型的時候使用哪種策略:

<?php
    namespace App\Providers;
    use App\Post;use App\Policies\PostPolicy;
    use Illuminate\Support\Facades\Gate;
    use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
    class AuthServiceProvider extends ServiceProvider{  
      /**
     * 應(yīng)用的策略映射。
     *
     * @var array
     */ 
     protected $policies = [  
          Post::class => PostPolicy::class,  
       ];   
     /**
     * 注冊任意應(yīng)用認(rèn)證、應(yīng)用授權(quán)服務(wù)
     *
     * @return void
     */ 
   public function boot()   
    {     
       $this->registerPolicies();   
            //   
     }
   }

策略自動發(fā)現(xiàn)

只要模型和策略遵循標(biāo)準(zhǔn)的 Laravel 命名約定,Laravel 就可以自動發(fā)現(xiàn)策略,而不是手動注冊模型策略。具體而言,策略必須位于包含模型的目錄下的 Policies 目錄中。因此,例如模型可以放在 app 目錄中,而策略可以放在 app/Policies 目錄中。此外,策略名稱必須與模型名稱匹配,并具有 Policy 后綴。因此,User 模型將對應(yīng)于 UserPolicy 類。

如果您想提供自己的策略發(fā)現(xiàn)邏輯,可以使用 Gate :: guessPolicyNamesUsing 方法注冊自定義回調(diào)。通常,應(yīng)該從應(yīng)用程序的 AuthServiceProviderboot 方法調(diào)用此方法:

use Illuminate\Support\Facades\Gate;
Gate::guessPolicyNamesUsing(function ($modelClass) {
    // return policy class name...
 });

{note} 在 AuthServiceProvider 中顯式映射的任何策略都將優(yōu)先于自動發(fā)現(xiàn)策略。

編寫策略

策略方法

一旦授權(quán)策略被注冊,你就可以為授權(quán)過后的每個動作添加方法。比如,我們在 PostPolicy 中定義一個 update 方法,它會判斷指定的 User 是否可以更新指定的 Post 實例。

update 方法接收 UserPost 實例作為參數(shù),并且應(yīng)該返回 true 或者 false 來表明用戶是否被授權(quán)更新指定的 Post 。所以在這個例子中,我們需要判斷用戶的 id 是否和 post 中的 user_id 匹配。

<?php
   namespace App\Policies;use App\User;
   use App\Post;class PostPolicy{  
       /**
     * 判斷該方法能否被用戶操作。
     *
     * @param  \App\User  $user
     * @param  \App\Post  $post
     * @return bool
     */ 
  public function update(User $user, Post $post) 
    {    
       return $user->id === $post->user_id;   
     }
 }

你可以繼續(xù)為這個授權(quán)策略定義額外的方法。比如,你可以定義 view 或者 delete 方法來授權(quán) Post 的多種行為,還可以為自定義的策略方法起一個你自己喜歡的名字。

{tip} 如果在 Artisan 控制臺生成策略時,使用 --model 選項,它會包含進(jìn)去 view,createupdatedelete 動作方法。

不包含模型方法

一些策略方法只接收當(dāng)前認(rèn)證通過的用戶作為參數(shù),而不用傳入與授權(quán)相關(guān)的模型實例。最常見的應(yīng)用場景就是授權(quán) create 動作。比如,如果你正在創(chuàng)建一篇博客,你可能希望先檢查一下當(dāng)前用戶是否有權(quán)限創(chuàng)建它。

當(dāng)定義一個不需要傳入模型實例的策略方法時,比如 create 方法,它就是不接收模型實例作為參數(shù)。你應(yīng)該定義這個方法只接收授權(quán)過的用戶作為參數(shù)。

/**
 * 判斷用戶是否可以創(chuàng)建請求。
 *
 * @param  \App\User  $user
 * @return bool
 */
 public function create(User $user){ 
    //
 }

訪客用戶

默認(rèn)情況下,如果傳入的 HTTP 請求不是經(jīng)過身份驗證的用戶發(fā)起的,那么所有的 gates 和策略都會自動返回 false。 然而,你可以允許這些授權(quán)檢查通過聲明一個『可選的』類型提示或為用戶參數(shù)定義提供 null 默認(rèn)值,從而傳遞到你的 gates 和策略中:

<?php
     namespace App\Policies;
     use App\User;use App\Post;class PostPolicy{  
       /**
     * 判斷用戶是否能更新指定帖子。
     *
     * @param  \App\User  $user
     * @param  \App\Post  $post
     * @return bool
     */ 
  public function update(?User $user, Post $post)  
    {     
      return $user->id === $post->user_id;  
     }
  }

策略過濾器

對特定用戶,你可能希望通過指定的策略授權(quán)所有動作。 要達(dá)到這個目的,可以在策略中定義一個 before 方法。 before 方法會在策略中其它所有方法之前執(zhí)行,這樣提供了一種方式來授權(quán)動作而不是指定的策略方法來執(zhí)行判斷。這個功能最常見的場景是授權(quán)應(yīng)用的管理員可以訪問所有動作:

public function before($user, $ability){
    if ($user->isSuperAdmin()) { 
       return true; 
     }
 }

如果你想拒絕某個用戶所有的授權(quán),你應(yīng)當(dāng)在 before 方法中返回 false 。如果返回值是 null ,那么授權(quán)會在這個策略中失敗。

{note} 策略類的 before 方法不會被調(diào)用,如果該類不包含與被檢查的功能名稱相符的方法。

使用策略授權(quán)動作

通過用戶模型

Laravel 內(nèi)置的 User 模型包含兩個有用的方法來授權(quán)動作: cancant。這個 can 方法需要指定授權(quán)的動作以及相關(guān)的模型。例如,判斷是否授權(quán)一個用戶更新指定的 Post 模型:

if ($user->can('update', $post)) { 
   //
}

如果指定模型的 「策略已被注冊 」, can 方法會自動調(diào)用合適的策略并返回一個 boolean 值。如果沒有策略注冊到這個模型,can 方法會嘗試調(diào)用和指定動作名稱相匹配的基于閉包的 Gate。

不需要指定模型的動作

記住,一些動作,比如 create 并不需要指定模型實例。在這種情況下,可傳遞一個類名給 can 方法。這個類名將被用于判定使用哪種策略授權(quán)動作:

use App\Post;if ($user->can('create', Post::class)) { 
   // 執(zhí)行相關(guān)策略中的 "create" 方法...
 }

通過中間件

Laravel 包含一個可以在請求到達(dá)路由或者控制器之前就進(jìn)行動作授權(quán)的中間件。默認(rèn)情況下, Illuminate\Auth\Middleware\Authorize 中間件被指定到你的 App\Http\Kernel 類中的 can 鍵上。讓我們用一個授權(quán)用戶更新博客的例子來講解一下 can 這個中間件的使用:

use App\Post;Route::put('/post/{post}', function (Post $post) {
    // 當(dāng)前用戶可以進(jìn)行更新操作...
})->middleware('can:update,post');

在這個例子中,我們傳給了 can 中間件兩個參數(shù)。第一個參數(shù)是需要授權(quán)的動作名稱,第二個參數(shù)是我們希望傳遞給策略方法的路由參數(shù)。在這種情況下,我們使用了「 隱式路由綁定」,一個 Post 模型會被傳遞給策略方法。如果用戶不被授權(quán)訪問指定的動作,這個中間件將會生成帶有 403 狀態(tài)碼的 HTTP 響應(yīng)。

不需要指定模型的動作

同樣,一些像 create 這樣的動作可能不需要模型實例。在這種情況下,你可以傳一個類名給中間件。當(dāng)授權(quán)這個動作時,這個類名將被用來判斷使用哪個策略:

Route::post('/post', function () {
    // 當(dāng)前用戶可以進(jìn)行創(chuàng)建操作...
 })->middleware('can:create,App\Post');

通過控制器輔助函數(shù)

除了在 User 模型中提供輔助方法以外,Laravel 也為繼承  App\Http\Controllers\Controller 這個基類的控制器提供了一個有用的 authorize 方法。就像 can 方法一樣,這個方法需要接收你想授權(quán)的動作和相關(guān)的模型作為參數(shù)。如果這個動作沒有被授權(quán), authorize 方法會拋出一個 Illuminate\Auth\Access\AuthorizationException 的異常,然后 Laravel 默認(rèn)的異常處理器會將這個異常轉(zhuǎn)化成帶有  403 狀態(tài)碼的 HTTP 響應(yīng)。

<?php
     namespace App\Http\Controllers;
     use App\Post;use Illuminate\Http\Request;
     use App\Http\Controllers\Controller;
     class PostController extends Controller{  
       /**
     * 更新指定博客帖子。
     *
     * @param  Request  $request
     * @param  Post  $post
     * @return Response
     * @throws \Illuminate\Auth\Access\AuthorizationException
     */ 
   public function update(Request $request, Post $post)  
     {     
       $this->authorize('update', $post);     
       // 當(dāng)前用戶可以更新博客...   
      }
  }

不需要指定模型的動作

和之前討論的一樣,一些動作,比如 create 并不需要指定模型實例的動作。在這種情況下,你可以傳遞一個類名給 authorize 方法。當(dāng)授權(quán)這個動作時,這個類名將被用來判斷使用哪個策略:

/**
 * 創(chuàng)建一個新的博客
 *
 * @param  Request  $request
 * @return Response
 * @throws \Illuminate\Auth\Access\AuthorizationException
 */
 public function create(Request $request){ 
    $this->authorize('create', Post::class);  
    // 當(dāng)前用戶可以新建博客...
  }

授權(quán)資源控制器

如果你使用的是 資源控制器,那么你就可以在控制器構(gòu)造方法里使用 authorizeResource 方法。該方法會把合適 can 中間件附加到資源控制器相應(yīng)的方法中。

authorizeResource 方法接收模板類名作為第一個參數(shù),包含模型 ID 的路由 / 請求參數(shù)的名稱作為其第二個參數(shù):

<?php
    namespace App\Http\Controllers;
    use App\Post;use Illuminate\Http\Request;
    use App\Http\Controllers\Controller;
    class PostController extends Controller{ 
       public function __construct() 
          {       
            $this->authorizeResource(Post::class, 'post');  
           }
     }

{提示} 你可以使用帶有 --model 選項的 make:policy 命令去快速生成基于給定模型的策略類::php artisan make:policy PostPolicy --model=Post。

通過 Blade 模板

當(dāng)編寫 Blade 模板時,你可能希望頁面的指定部分只展示給授權(quán)訪問指定動作的用戶。比如,你可能希望只展示更新的表單給有權(quán)更新博客的用戶。在這樣情況下,你可以使用 @can@cannot 等一系列指令:

@can('update', $post) 
  <!-- The Current User Can Update The Post -->
@elsecan('create', App\Post::class)  
  <!-- The Current User Can Create New Post -->
@endcan
@cannot('update', $post) 
  <!-- The Current User Can't Update The Post -->
@elsecannot('create', App\Post::class)
  <!-- The Current User Can't Create New Post -->
 @endcannot

這些指令是編寫 @if@unless 語句的捷徑。 @can@cannot 語句分別轉(zhuǎn)化為以下語句:

@if (Auth::user()->can('update', $post))  
  <!-- The Current User Can Update The Post -->
@endif
@unless (Auth::user()->can('update', $post))   
 <!-- The Current User Can't Update The Post -->
@endunless

不依賴模型的動作

與大多數(shù)其他授權(quán)方法一樣,如果動作不需要模型實例,則可以將類名傳遞給 @ can@ cannot 指令:

@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
本文章首發(fā)在 LearnKu.com 網(wǎng)站上。