天天看點

Laravel 使用者授權 Gate和Policy

要點:

  • Laravel 有 2 種主要方式來實作使用者授權:gates 和政策。
  • Gates 接受一個目前登入使用者的執行個體作為第一個參數。并且接收可選參數,比如相關的Eloquent 模型。
  • 用指令生成政策

    php artisan make:policy PostPolicy --model=Post

    --model

    參數生成的内容包含CRUD方法
  • Gate用在模型和資源無關的地方,Policy正好相反。
<?php

namespace App\Policies;

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

class PostPolicy
{
    use HandlesAuthorization;

    /**
     * Determine whether the user can view the post.
     *
     * @param  \App\User  $user
     * @param  \App\Post  $post
     * @return mixed
     */
    public function view(User $user, Post $post)
    {
        //
    }

    /**
     * Determine whether the user can create posts.
     *
     * @param  \App\User  $user
     * @return mixed
     */
    public function create(User $user)
    {
        //
    }

    /**
     * Determine whether the user can update the post.
     *
     * @param  \App\User  $user
     * @param  \App\Post  $post
     * @return mixed
     */
    public function update(User $user, Post $post)
    {
        //
    }

    /**
     * Determine whether the user can delete the post.
     *
     * @param  \App\User  $user
     * @param  \App\Post  $post
     * @return mixed
     */
    public function delete(User $user, Post $post)
    {
        //
    }
}

           

操作流程:

  1. 建立Post表及Model檔案

    php artisan make:migrate create_posts_table

    php artisan make:model Post

    表資訊
public function up()
    {
        Schema::create('posts', function (Blueprint $table) {
            $table->increments('id');
            $table->string('title');
            $table->integer('user_id')->unsigned();
            $table->text('body');
            $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
            $table->timestamps();
        });
    }
           

填充資料,打開UserFactory添加

$factory->define(App\Post::class, function (Faker $faker) {
    return [
        'title' => $faker->sentence,
        'body' => $faker->paragraph,
        'user_id' => factory(\App\User::class)->create()->id,
    ];
});
           

Post表内容

Laravel 使用者授權 Gate和Policy

image.png

  1. routes/web.php添加

    Route::resource('posts', 'PostsController');

  2. 定義Gate

    打開 Proviers/AuthServiceProvider.php,修改boot方法

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

        // Gates 接受一個使用者執行個體作為第一個參數,并且可以接受可選參數,比如 相關的 Eloquent 模型:
        Gate::define('update-post', function ($user, $post) {
            // return $user->id == $post->user_id;
            return $user->owns($post);
        });
    }
           

這裡,在User模型中定義了own方法

public function owns($post)
    {
        return $post->user_id === $this->id;
    }
           
  1. PostsController中,隻寫一個show方法
// Gate 示範
    public function show($id)
    {
        $post = Post::findOrFail($id);

        \Auth::loginUsingId(2);

        $this->authorize('update-post', $post);

        if (Gate::denies('update-post', $post)) {
            abort(403, 'sorry');
        }


        // compact('post') 等價于 ['post' => $post]
        return view('posts.view', compact('post'));
        // return $post->title;
    }
           
  1. 通路

    /posts/1

    。會報403。這是因為我們是用user_id為2登入。
Laravel 使用者授權 Gate和Policy
  1. 如果注釋

    $this->authorize('update-post', $post);

    ,就會顯示:
    Laravel 使用者授權 Gate和Policy
  2. 視圖中判斷Policy,如果post的user_id是目前登入使用者,顯示編輯連結。
@can('update', $post)
<a href="#">編輯</a>
@endcan
           

@can 和 @cannot 各自轉化為如下聲明:

@if (Auth::user()->can('update', $post))
    <!-- 目前使用者可以更新部落格 -->
@endif

@unless (Auth::user()->can('update', $post))
    <!-- 目前使用者不可以更新部落格 -->
@endunless
           

參考:

https://d.laravel-china.org/docs/5.5/authorization