要點(diǎn):
- Laravel 有 2 種主要方式來實(shí)現(xiàn)用戶授權(quán):gates 和策略。
- Gates 接受一個(gè)當(dāng)前登錄用戶的實(shí)例作為第一個(gè)參數(shù)盅藻。并且接收可選參數(shù),比如相關(guān)的Eloquent 模型。
- 用命令生成策略
php artisan make:policy PostPolicy --model=Post
帶--model
參數(shù)生成的內(nèi)容包含CRUD方法 - Gate用在模型和資源無關(guān)的地方窑眯,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();
});
}
填充數(shù)據(jù)澡罚,打開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表內(nèi)容
image.png
routes/web.php添加
Route::resource('posts', 'PostsController');
定義Gate
打開 Proviers/AuthServiceProvider.php伸但,修改boot方法
public function boot()
{
$this->registerPolicies();
// Gates 接受一個(gè)用戶實(shí)例作為第一個(gè)參數(shù),并且可以接受可選參數(shù)留搔,比如 相關(guān)的 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中,只寫一個(gè)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') 等價(jià)于 ['post' => $post]
return view('posts.view', compact('post'));
// return $post->title;
}
- 訪問
/posts/1
隔显。會(huì)報(bào)403却妨。這是因?yàn)槲覀兪怯胾ser_id為2登錄。
image.png
-
如果注釋
$this->authorize('update-post', $post);
括眠,就會(huì)顯示:
image.png 視圖中判斷Policy彪标,如果post的user_id是當(dāng)前登錄用戶,顯示編輯鏈接掷豺。
@can('update', $post)
<a href="#">編輯</a>
@endcan
@can 和 @cannot 各自轉(zhuǎn)化為如下聲明:
@if (Auth::user()->can('update', $post))
<!-- 當(dāng)前用戶可以更新博客 -->
@endif
@unless (Auth::user()->can('update', $post))
<!-- 當(dāng)前用戶不可以更新博客 -->
@endunless