“中国要复兴、富强,必须在开源软件领域起到主导作用,为了国家安全和人类发展,责无旁贷,我们须为此而奋斗”——By:云客
在本系列的前面介绍了实体基础和配置系统的部分内容,现在已有足够的预备知识,我们结合一个具体的实体列子来看一看实体是怎么实现的,本篇讲解用户角色实体。
权限判断:
判断用户是否具备某权限是从用户账户对象中得知的,默认账户对象为:
Drupal\Core\Session\UserSession
实例化账户对象是在以下方法中:
Drupal\user\Authentication\Provider\Cookie::getUserFromSession(SessionInterface $session);
在数据库中:
users_field_data表:储存用户基本信息,比如密码、邮箱、语言等等
user__roles表:储存用户角色信息,但并不包含角色拥有的权限,从该表得到用户拥有哪些角色
在用户账户中有三个和权限相关的方法:
public function getRoles($exclude_locked_roles = FALSE)
得到用户所属的角色,返回一个数组,系统有两个特殊角色:匿名角色、已注册用户角色,参数为true时排除这两个特殊角色
public function hasPermission($permission)
返回bool,表明用户是否有某权限,uid为1的用户账户为系统维护账户,在系统安装时设置,它拥有所有权限
protected function getRoleStorage()
得到用户角色实体的储存处理器:\Drupal::entityManager()->getStorage('user_role');
可以看出针对权限的检查是在实体系统里面进行的:
实体管理器的服务id是:entity.manager
类:Drupal\Core\Entity\EntityManager
但该服务已经在8.0中弃用了,将在9.0中移除,实际的工作在以下服务中进行:
服务ID: entity_type.manager
类:Drupal\Core\Entity\EntityTypeManager
从实体类型管理器中可以获取用户角色实体的实体类型对象(也是插件定义对象),插件id:“user_role”
\Drupal::entityTypeManager()->getDefinition(“user_role”, TRUE);
通过该对象可以知道角色实体的相关元信息,我们来看一看角色实体是怎么实现的,是如何进行权限判断的
用户角色实体:
类为:Drupal\user\Entity\ Role
这是一个配置实体,用于权限系统,它的继承关系如下:
Drupal\Core\Entity\Entity: (Drupal\Core\Entity\EntityInterface)
Drupal\Core\Config\Entity\ConfigEntityBase: (Drupal\Core\Config\Entity\ConfigEntityInterface)
Drupal\user\Entity\Role:(Drupal\user\RoleInterface)
它直接继承自配置实体基类,详见本系列的配置实体基类主题
实现了角色接口:Drupal\user\RoleInterface(该接口又继承自配置实体接口)
角色接口描述了角色实体对外的功能,如得到权限信息、授权、去权、判断有无权限、设置为管理员等等
请先看它的释文定义,用户角色实体是一个比较简单、清晰的配置实体,也是系统启动以来我们会遇到的第一个实体,后续主题中将会多次以他作为列子。
如果你是跟随本系列发布顺序一直读到这里,那么很容易就明白这个类的实现,如不明白请先阅读本系列已发布的相关内容,这里只说明几点:
一个用户角色实体对象代表着一个用户角色,其中的$is_admin属性用于指示该角色是否为超级管理员角色,该角色授予维护账户,拥有所有的权限。
在系统中每一项具体的权限都用一个字符串类型的权限标志符来表示,模块可以通过$module.permissions.yml文件去定义,角色拥有的权限储存在角色实体对象的$permissions属性中,它是一个数组,值为权限标识符,角色是否有某权限等价于该权限的权限标识符是否在该数组中,但超级管理员角色并不关注该数组,它为空数组,一旦判断是超级管理员角色,则默认拥有所有权限。
$weight属性用于指示角色的权重,整型数值类型,用于管理界面的列表排序,值越大越靠后,默认匿名角色为0,已经认证角色为1,超级管理员为2,在无设置时将在最大权重值上累加一。
用户角色实体储存处理器:
实体在释文中指定自己的储存处理器,实体对象由其实例化,用户角色实体储存处理器为:
Drupal\user\RoleStorage
该类非常简单,因为它继承自配置实体储存处理器基类,该基类完成了主要的储存工作(介绍该基类的主题在本篇前已发布,请查阅),一个账户可以拥有多个角色,因此在该储存处理器中实现了判断用户是否具备某权限的方法:
public function isPermissionInRoles($permission, array $rids)
它根据用户账户对象提供的角色信息实例化对应的角色实体对象,再判断它们是否有权,一旦其中之一有权则认为该账户对象有权,这里可以看出系统的权限架构是以“有权”优先的,而不是“无权”优先,也就是说当用户具备两个角色时,针对某权限一个允许,另一个禁止,系统将以允许为准。
用户角色实体的配置信息储存在数据库的配置config表中,默认安装下有三个角色,表中name字段名为:
user.role.administrator
user.role.anonymous
user.role.authenticated
可以在控制器中执行以下代码查看其内容:
$a = \Drupal::config('user.role.authenticated')->getOriginal(NULL, false);
print_r($a);
exit();
对用户角色实体的操作示例代码如下:
$role = \Drupal\user\Entity\Role::load('authenticated'); //加载并实例化角色实体对象
$role->grantPermission('access comments'); //进行授权
$role->save(); //保存实体
本篇就介绍到这里,算是对权限系统的了结,结合本系列前面的相关主题,读者应该已经明白drupal的权限是如何检查、如何储存表示的,关于用户角色实体的其他内容,比如链接、列表构建处理器、表单处理器、访问控制处理器等,因为和其他实体具备相似性,所以在后续的实体相关概念中统一介绍。
补充说明:
1、账户、角色、权限的官网文档地址:
https://api.drupal.org/api/drupal/core%21core.api.php/group/user_api/8.3.x
反馈互动