- 生成策略類
$ php artisan make:policy UserPolicy
# 包含curd所有方法的
$ php artisan make:policy UserPolicy --model=User
- 在
AuthServiceProvider中注冊(cè)策略類, 位于app/Providers/AuthServiceProvider.php
// 方法① 通過(guò)在類變量$policies的注冊(cè)
protected $policies = [
'App\Models\User' => 'App\Policies\UserPolicy',
// User::class => UserPolicy::class, // 效果同上
];
// 方法② 通過(guò)在boot()方法中注冊(cè)
public function boot()
{
$this->registerPolicies();
// 修改策略自動(dòng)發(fā)現(xiàn)的邏輯
Gate::guessPolicyNamesUsing(function ($modelClass) {
// 動(dòng)態(tài)返回模型對(duì)應(yīng)的名稱
return 'App\Policies\\' . class_basename($modelClass) . 'Policy';
});
}
- 策略的使用
/**
* 只有管理員或用戶本人才能修改。
*
* @param \App\Models\User $currentUser
* @param \App\Models\User $user
* @return \Illuminate\Auth\Access\Response|bool
*/
public function update(User $currentUser, User $user)
{
return $currentUser->can('manage_users') || $currentUser->id === $user->id;
}
- 策略的過(guò)濾
對(duì)特定用戶,你可能希望通過(guò)指定的策略授權(quán)所有動(dòng)作。 要達(dá)到這個(gè)目的,可以在策略中定義一個(gè) before 方法。before 方法會(huì)在策略中其它所有方法之前執(zhí)行,這樣提供了一種方式來(lái)授權(quán)動(dòng)作而不是指定的策略方法來(lái)執(zhí)行判斷。這個(gè)功能最常見(jiàn)的場(chǎng)景是授權(quán)應(yīng)用的管理員可以訪問(wèn)所有動(dòng)作:
/**
* 權(quán)限判斷之前確定操作用戶是否是超管
* @param User $currentUser
* @param string $ability 預(yù)備做的操作
* @return bool
*/
public function before(User $currentUser, $ability)
{
if ($currentUser->isAdmin()) {
// 只有false才會(huì)繼續(xù)做權(quán)限判斷
return true;
}
}
- 權(quán)限策略的使用
Laravel 應(yīng)用內(nèi)置的 User 模型包含 2 個(gè)有用的方法來(lái)授權(quán)動(dòng)作:can 和 cant / cannot。can 方法需要指定授權(quán)的動(dòng)作和相關(guān)的模型。( cant 和 cannot 處理效果是一樣的, 同英語(yǔ) can't 和 can not )
// controller中操作
// $this->authorize('update', $user); // 電腦的實(shí)現(xiàn)
// 接口返回
if (request()->user()->cant('update')) {
return response()->json(['code' => 403, 'msg' => '無(wú)權(quán)操作']);
};
注:
通過(guò) authorize()方法操作會(huì)報(bào)出異常
處理拋出的授權(quán)異常:在app/Exceptions/Handler.php中判斷異常類型,若是授權(quán)異常,則跳轉(zhuǎn)到無(wú)權(quán)限頁(yè)面
/**
* Render an exception into an HTTP response.
* @param \Illuminate\Http\Request $request
* @param Exception $exception
* @return \Illuminate\Http\RedirectResponse|\Symfony\Component\HttpFoundation\Response
*/
public function render($request, Exception $exception)
{
if ($exception instanceof AuthorizationException) {
return redirect()->guest(route('admin.permission-denied'));
}
return parent::render($request, $exception);
}