要點:
- Laravel 有 2 種主要方式來實作使用者授權:gates 和政策。
- Gates 接受一個目前登入使用者的執行個體作為第一個參數。并且接收可選參數,比如相關的Eloquent 模型。
- 用指令生成政策
帶php artisan make:policy PostPolicy --model=Post
參數生成的内容包含CRUD方法--model
- 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)
{
//
}
}
操作流程:
- 建立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表内容

image.png
- routes/web.php添加
Route::resource('posts', 'PostsController');
-
定義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;
}
- 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;
}
- 通路
。會報403。這是因為我們是用user_id為2登入。/posts/1
- 如果注釋
,就會顯示:$this->authorize('update-post', $post);
Laravel 使用者授權 Gate和Policy - 視圖中判斷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