Policy(即策略)是在特定模型或者资源中组织授权逻辑的类,用来处理用户授权动作。

比如在博客程序中会有一个 Article 模型,这个模型就会有一个相应的 ArticlePolicy 来对用户的操作进行授权,比如在修改一篇文章时,我们会这样写:

1
2
3
4
5
6
$article = Article::find(1)
// 校验这篇是否属于当前用户
if ($article->user_id == Auth::id()) {
// 修改文章
}
return ture;

Policy 其实就是将校验的逻辑从控制器转移到相对应的模型策略 (ArticlePolicy) 中。

生成 Policy

使用 php artisan make:policy ArticlePolicy 命令生成 Policy,保存在 app/Policies 目录下。

注册 Policy

然后在 app/Providers/AuthServiceProvider.phppolicies 数组中注册该策略,将 Article 模型与对应的 ArticlePolicy 策略进行绑定。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<?php

namespace App\Providers;

use App\Models\Article;
use App\Policies\ArticlePolicy;
use Illuminate\Support\Facades\Gate;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;

class AuthServiceProvider extends ServiceProvider
{
/**
* 应用的策略映射。
*
* @var array
*/
protected $policies = [
Article::class => ArticlePolicy::class,
];

/**
* 注册任意用户认证、用户授权服务。
*
* @return void
*/
public function boot()
{
$this->registerPolicies();

//
}
}

编写 Policy 校验逻辑

接下来就在 ArticlePolicy 策略中编写校验用户是否拥有修改文章的权限的方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php

namespace App\Policies;

use App\Models\Article;
use App\User;

class ArticlePolicy
{
public function update(User $user, Article $article)
{
return $user->id == $article->user_id;
}
}

update 方法中判断文章作者id是否等于当前登录的用户id,返回 true 或 false。true 可以进行修改操作,false 则会抛出没有权限。

使用 Policy

然后就是在控制器中的使用了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php

namespace App\Http\Controllers;

use App\Models\Article;
use Illuminate\Http\Request;

class ArticleController extends Controller
{
public function edit(Request $request, Article $article)
{
// 校验用户是否有操作权限
$this->authorize('update', $article);

// 更新文章
$article->fill($request->all());
$article->save();
}
}

authorize 的第一个参数表示本次验证使用 ArticlePolicy 里面的 update 方法, $article 实例用来判断使用哪一种策略,当然也可以不用指定具体实例,只需要传递一个类名。

1
$this->authorize('update', Article::class);