第八章总结与问题梳理
8.1多角色用户权限
本节教程使用了一种普遍的角色+权限的后台权限管理模式,安装扩展包叫做laravel-permission
。我以前是做CMS系统的,所以对这种模式很熟悉,只是这里多了一层关于模型的判断,而非以前我建个role_user表直接让user_id 与 role_id的进行关联,本教程只有user模型,虽然没接触过其他模型的例子,但扩展性更强是毋庸置疑的了。
在这里具体分析一下各个表,梳理一下
1.roles 角色模型表
很容易理解,不多解释。关于guard_name字段“守卫”的功能参看laravel-permission使用多个守卫( guard ) ,多了一层命名空间的判断。
2.permissions 权限模型表
同上,也很容易理解
3.model_has_roles模型与角色的关联表
这里类似于我过去建立的role_user表,现在变成了和model绑定,user_model的id就相当于过去的user_id,也算容易理解。
$user = App\Models\User::find(2);
$user->assignRole('writer', 'admin');
就是向这个表内的user模型对应的id=2绑定role_id数据。
4.role_has_permissions角色拥有的权限关联表
不难理解。
5.model_has_permissions 模型与权限关联表
这张表应该是直接赋予某个用户权限的表,因为教程里没有直接给用户授权的逻辑,因此这里是空的。
8.2站点权限部署
本节要解决两个需求
- 拥有
manage_contents
权限的用户允许管理站点内所有话题和回复,包括编辑和删除动作; - Horizon 的控制面板,只有
站长
才有权限查看。
这里涉及到了授权策略,这个在之前的教程章节中学习过如何建立某个特定模型的授权策略,我们将创建的策略都建立在App\Policies目录中,并在App\Providers\AuthServiceProvider中注册。
授权策略涉及了服务容器和服务提供者相关的概念,说实话,我是在最近才接触到这些概念,每次看手册这块内容时脑袋里都是一团浆糊,现在是2020年8月15日,等我以后彻底弄明白了,会写一篇文章总结自己的收获,并在此留下文章链接。现在暂时还是很懵懂。
先顺着刚才的话,解决
Horizon 的控制面板,只有
站长
才有权限查看。class AuthServiceProvider extends ServiceProvider { /** * 应用程序的策略映射。 * * @var array */ protected $policies = [ \App\Models\Reply::class => \App\Policies\ReplyPolicy::class, \App\Models\Topic::class => \App\Policies\TopicPolicy::class, ]; /** * 注册任何应用程序 authentication / authorization 服务。 * * @return void */ public function boot() { $this->registerPolicies(); // 修改策略自动发现的逻辑 Gate::guessPolicyNamesUsing(function ($modelClass) { // 动态返回模型对应的策略名称,如:// 'App\Model\User' => 'App\Policies\UserPolicy', return 'App\Policies\\'.class_basename($modelClass).'Policy'; }); \Horizon::auth(function($request){ //是否登录 if(\Auth::check()){ //是否是站长 return \Auth::user()->hasRole('Founder'); }else{ return false; } }); } }
针对上面的代码梳理一下,首先我们
$policies
中添加了需要注册的策略映射关系,在boot
方法中,用registerPolicies()
方法调用Gate
对进行注册。此前我们修改了策略自动发现的逻辑。
下面对\horizon路由进行访问权限的设定,方法是调用\Horizon
模型的auth
方法接收一个回调函数返回的结果。还没有彻底明白这里为什么这样写,因为与之前的策略注册方式不同,希望以后能明白吧。
另一个需求是
- 拥有
manage_contents
权限的用户允许管理站点内所有话题和回复,包括编辑和删除动作;
<?php
namespace App\Policies;
use Illuminate\Auth\Access\HandlesAuthorization;
class Policy
{
use HandlesAuthorization;
public function before($user, $ability)
{
// 如果用户拥有管理内容的权限的话,即授权通过
if ($user->can('manage_contents')) {
return true;
}
}
}
我们将使用授权策略的策略过滤器
机制来实现统一授权的目的
手册原文:
before 方法将在策略上的任何其他方法之前执行,从而使您有机会在实际调用预期的策略方法之前授权操作。此功能最常用于授权应用程序管理员执行任何操作
也就是说这个before
方法可以在任何一个策略中使用,而我们这里在Policy
中使用,就相当于在所有继承Policy
的策略中使用。
8.3-8.7都是在围绕Laravel Administrator 这款扩展
教程中介绍了administrator的配置选项,以及配合使用扩展所要做的一些修改,值得注意的知识点有:
- Eloquent 修改器
这里是为了处理密码保存时,进行加密的操作,以及头像保存目录的添加,详见 8.4管理后台-修改用户密码
- 创建模型链接的辅助方法
能够通过Eloquent数据模型获得跳转链接,详见8.6后台管理-话题模型配置
- 防范XSS攻击
由于后台没有blade模板进行转义,administrator中output输出的HTML内容使用了Laravel自带的e()
函数进行转义。此处我不太明白,之前发帖功能里面需要用HTMLPurifier for Laravel扩展和这里的e()
函数作用是否是相同的。
- 站点配置中清空缓存操作
<?php
return [
·
·
·
// 你可以自定义多个动作,每一个动作为设置页面底部的『其他操作』区块
'actions' => [
// 清空缓存
'clear_cache' => [
'title' => '更新系统缓存',
// 不同状态时页面的提醒
'messages' => [
'active' => '正在清空缓存...',
'success' => '缓存已清空!',
'error' => '清空缓存时出错!',
],
// 动作执行代码,注意你可以通过修改 $data 参数更改配置信息
'action' => function(&$data)
{
\Artisan::call('cache:clear');
return true;
}
],
],
];
我目前的程序中,执行php artisan cache:clear
时会报错
Failed to clear cache. Make sure you have the appropriate permissions.
不知道为什么会导致这个原因。
然而这里的
\Artisan::call('cache:clear');
却可以执行。也算我目前的一个未解之谜。
8.8后台访问权限
本节不难理解
值得我个人注意的是,对于闭包函数的调用问题
/*
* 权限控制的回调函数。
*
* 此回调函数需要返回 true 或 false ,用来检测当前用户是否有权限访问后台。
* `true` 为通过,`false` 会将页面重定向到 `login_path` 选项定义的 URL 中。
*/
'permission' => function () {
// 只要是能管理内容的用户,就允许访问后台
return Auth::check() && Auth::user()->can('manage_contents');
},
下面是在控制器中调用上面的函数(错误演示)
if(config('administrator.permission')){
return redirect(url(config('administrator.uri')),302);
}
注意到了吗?我这里忘记加()
了,调用闭包函数要在后面加括号。
if(config('administrator.permission')()){
return redirect(url(config('administrator.uri')),302);
}
推荐文章: