---
# System prepended metadata

title: laravel Gate authoize policy
tags: [Laravel]

---

# laravel Gate authoize policy
歐洲laravel 
https://www.youtube.com/watch?v=B2M3FCjRz6w

記得要定義關係喔


因為gate註冊crud太亂了才有policy
但不是他比較好


命名 post.update
因為會對應controller所以才用 .
這是它命名規則


**authoize的預設規則**
https://www.bilibili.com/video/BV1Ue411p7te/?spm_id_from=333.788.recommend_more_video.17

必看(https://laracasts.com/series/laravel-from-scratch-2018/episodes/27)

## blade使用時
@can外面包一個auth
這樣不需要才不用讓權限去跑
![](https://i.imgur.com/7CCrIsg.png)


## view 用boolean最好要加入問號
![](https://i.imgur.com/9DdDAjJ.jpg)


## gate

去auth專屬的provider註冊

這才是全域

### Gate::define
![](https://i.imgur.com/vNwp8LX.png)
**註冊**
第一個是名字(能力的名字)

第二參數是閉包,有兩個參數
(第一個一定是user 第二個是要自已傳入,再引入時候,不需要用到時候可以不用傳入 沒有要對model的user做判斷時候 )
(閉包要return喔)



**使用**
![](https://i.imgur.com/cg2e6Sz.png)
用 Gate::denies
第一個參數是user(驗證過的)
第二參數是要傳入的

記住
這要自己用about
他不會自動幫你回傳錯誤status

只是你看截圖
你這樣要findOrfaill
但可以又model綁定方法
這種
Gate::allow('update-post',$post)
這邊的$post經過model了 






### authorize helper(controller驗證)

基底的 App\Http\Controllers\Controller 類別包含了 Laravel 使用的 AuthorizesRequests trait。此 trait 提供了 authorize 方法，它可以被用於快速授權一個給定的行為，當無權限執行該行為時會拋出 HttpException。


![](https://i.imgur.com/TT3YgoI.png)
可以取代
```
if(Gate::denies('delete-post',$post)){
    about(403,'no use')
}
```

變成
`$this->authorize('delete-post',$post);`
可以不用在about 更快

但這也要findOrFail
在傳入post


### forUser()
![](https://i.imgur.com/DnuqK9d.png)

$user = User::find(1);

Gate::forUser($user)->denise('update-post',$post)
=> true
**這個使用者可以使用當前的post,他有權限**

Gate::forUser($user)->allows('update-post',$post)
=> false
**這個使用者可以使用所有的post,他有權限**


### before after
before在所有define之前
after在所有gate之後

一般都適用before定義超級管理員
![](https://i.imgur.com/9v1uYKs.png)
這邊是限定超級管理員只能update-post
但可以拔掉就全部都能了
閉包 就return ture就好了

## policy
https://mark-lin.com/posts/20181214/
https://ithelp.ithome.com.tw/articles/10223360



**因為gate這樣一個一個定義太麻煩 也不好閱讀
所以產生policy**


針對一個 Model 或者資源限制權限的時候，可以使用的機制。
`php artisan make:policy PostPolicy --model=Post`

第一步 註冊
![](https://i.imgur.com/eltndwV.png)
要在gate 那邊註冊 因為他本來就是gate 只是把它用一個資料夾叫policy來管理而已
這邊重點
要用.  ex post.update這種去命名 不能跟之前一樣用post-update這樣

**下一步就是進階用resoucre**
這對應的是
**post.create** 
**post.view** 
**post.update** 
**post.delete**
![](https://i.imgur.com/9snfsqo.png)
 
你可以想成它是對應controller的


**這樣定義resource有一個缺點**
要知道她是對應哪個然後還有post 之類的前墜
多了就很難管理
所以

到最上面array那邊註冊model
![](https://i.imgur.com/Ng9KMrD.png)
因為下面有
this->regiserPolicies
所以他會去找model
這樣
只要你controller傳進來的
是經過model find 找到的那個
就會自動對應


controller部分
可以$this->authorize('update',$post)這樣去對應
但也可以
$this->authorize($post)
這會自動對照你controller名稱
規則看下面
**這邊很特別store 跟 create是對照 create**
[
    'show' => 'view'
    'create' => 'create'
    'store' => 'create'
    'edit' => 'update'
    'update' => 'update'
    'destory' => 'delete'
]








**看不懂請看程式碼**
```
<?php

namespace App\Policies;

use App\User;
use App\Animal;
use Illuminate\Auth\Access\HandlesAuthorization;

class AnimalPolicy
{
    use HandlesAuthorization;

    public function before($user, $ability)
    {
        if ($user->isSuperAdmin()) {
            return true;
        }
    }
    /**
     * Determine whether the user can view any animals.
     *
     * @param  \App\User  $user
     * @return mixed
     */
    public function viewAny(User $user)
    {
        //未登入也可以看所有動物資料，不需要用到這個方法
    }

    /**
     * Determine whether the user can view the animal.
     *
     * @param  \App\User  $user
     * @param  \App\Animal  $animal
     * @return mixed
     */
    public function view(User $user, Animal $animal)
    {
        //未登入也可以看動物資料，不需要用到這個方法
    }

    /**
     * Determine whether the user can create animals.
     *
     * @param  \App\User  $user
     * @return mixed
     */
    public function create(User $user)
    {
        // 登入後認證授權確認皆可以創建送養動物資料，所以不需要製作這方法
        // 是否有權限操作，請參考前幾天 Victor 的鐵人賽文章。 
    }

    /**
     * Determine whether the user can update the animal.
     *
     * @param  \App\User  $user
     * @param  \App\Animal  $animal
     * @return mixed
     */
    public function update(User $user, Animal $animal)
    {
        // 修改動物資料必須檢查，動物是否是由該會員新建的，利用animal 的user_id 判斷
        if ($user->id === $animal->user_id) {
            return true;
        }
        return false;
    }

    /**
     * Determine whether the user can delete the animal.
     *
     * @param  \App\User  $user
     * @param  \App\Animal  $animal
     * @return mixed
     */
    public function delete(User $user, Animal $animal)
    {
        // 刪除動物資料必須檢查，動物是否是由該會員新建的，利用animal 的user_id 判斷
        if ($user->id === $animal->user_id) {
            return true;
        }
        return false;
    }

    /**
     * Determine whether the user can restore the animal.
     *
     * @param  \App\User  $user
     * @param  \App\Animal  $animal
     * @return mixed
     */
    public function restore(User $user, Animal $animal)
    {
        // 軟體刪除後「復原用」類似丟到資料丟到垃圾桶後，要再把資料救回來時判斷。
        // 因為沒有實作軟刪除的部分，這部分直接空著
    }

    /**
     * Determine whether the user can permanently delete the animal.
     *
     * @param  \App\User  $user
     * @param  \App\Animal  $animal
     * @return mixed
     */
    public function forceDelete(User $user, Animal $animal)
    {
        // 軟體刪除後，強制刪除資料表的動物資料。類似資料丟到垃圾桶後，要永久刪除資料的時判斷的邏輯。
        // 因為沒有實作軟刪除的部分，這部分直接空著
    }
}
```

## blade 方面 
因為policy跟gate都是controller再用
但這樣你blade還是看得到按鈕

@can('update', $post)
一樣第一個是policy或gate的名稱
第二個是model find的那個 一樣要實例


## 使用時機
policy在使用resoucre 跟 model的情況下是最好
對於特定資源跟model的權限許可


gate比較是全域的 跟model比較沒關係的定義用gate


但公司很厲害使用
gate放在model裡面


## middware
用can middware 這本來就註冊了
:後面一樣是船參數 所以這會去叫home.secrect的gate那邊
 
![](https://i.imgur.com/d704Eit.png)


![](https://i.imgur.com/zjIV12A.png)
## 個人總結
註冊可以在
prodioder那邊註冊
用gate
太亂所以有另外開的較policy對應crud

使用上
controller呼叫
authorize
gate
auth->user()->can()

或在blade使用
@can()
或在route用middware('can:update,product')
對應的是
Route::resorce('/product',prodcutController);

can後面接對應的註冊名稱
第二個是參數
因為是resorce所以會自動傳入


基本上使用可以一個參數 往上看

不然就兩個參數通用
別特別記了


基本上都用polcy
全域像是超級管理員那種才會去povider註冊

## permission來源
第一階段思考要放進database
![](https://i.imgur.com/DEj1qQ2.jpg)

驗證
![](https://i.imgur.com/5HCPnyr.jpg)


###### tags: `Laravel`
