专栏首页码神联盟Shiro系列 | 《Shiro开发详细教程》第三章:Shiro授权流程-下

Shiro系列 | 《Shiro开发详细教程》第三章:Shiro授权流程-下

本文目录:

► 第三章:Shiro授权-下

► 3.4 Permission

► 3.5 授权流程

下节预告

► 第四章:Shiro中Ini配置(预告)

► 4.1 SecurityManger根对象(预告)

► 4.2 ini配置(预告)

3.4 Permission

字符串通配符权限:

规则:资源标识符:操作:对象实例ID

注:即对哪个资源的哪个实例可以进行什么操作

其默认支持通配符权限字符串:

“:”表示资源/操作/实例的分割;

“,”表示操作的分割;

“*” 表示任意资源/操作/实例。

1. 单个资源、单个权限

subject.checkPermissions("user:update");

2. 单个资源,多个权限

ini配置文件:

role4=user:update,user:delete

然后通过如下代码判断:

subject.checkPermissions("user:update", "user:delete");

用户拥有资源“user”的“update”和“delete”权限,可以简写为:

ini 配置(表示角色4拥有user 资源的 update 和 delete 权限)

role4="user:update,delete"

接着可以通过如下代码判断

subject.checkPermissions("user:update,delete");

通过“user:update,delete”验证“user:update,user:delete”是没问题的,但是反过来是规则不成立。

3. 单个资源、全部权限

Ini配置:

role5="user:create,update,delete,view"

然后通过如下代码判断:

subject.checkPermissions("user:create,delete,update:view");

用户拥有资源“user”的“create”、“update”、“delete”和“view”所有权限。

如上可以简写成:

ini 配置文件(表示角色 5 拥有user 的所有权限)

role5=user:*

也可以简写为(推荐上边的写法):

role5=user

然后通过如下代码判断:

subject.checkPermissions("user:*"); subject.checkPermissions("user");

通过“user:*”验证“user:create,delete,update:view”可以,但是反过来是不成立的。

4. 所有资源、全部权限

ini 配置:

role6=*:view

然后通过如下代码判断:

subject.checkPermissions("user:view");

用户拥有所有资源的“view”所有权限。假设判断的权限是“"user:view”,那么需要“role6=::view”这样写才行。

5. 实例级别的权限

a) 单个实例、单个权限

ini 配置:

role7=user:view:1

对资源 user 的 1 实例拥有 view 权限。

然后通过如下代码判断:

subject.checkPermissions("user:view:1");

b) 单个实例、多个权限

ini 配置:

role7="user:update,delete:1"

对资源 user 的 1 实例拥有 update、delete 权限。

然后通过如下代码判断 :

subject.checkPermissions("user:delete,update:1");

subject.checkPermissions("user:update:1", "user:delete:1");

c) 单个实例、所有权限

ini 配置:

role7=user:*:1

对资源 user 的 1 实例拥有所有权限。

然后通过如下代码判断:

subject.checkPermissions("user:update:1","user:delete:1","user:view:1");

d) 所有实例、单个权限

ini 配置:

role7=user:auth:*

对资源 user 的 1 实例拥有所有权限。

然后通过如下代码判断:

subject.checkPermissions("user:auth:1", "user:auth:2");

e) 所有实例、所有权限

ini 配置:

role7=user:*:*

对资源 user 的 1 实例拥有所有权限。

然后通过如下代码判断:

subject.checkPermissions("user:view:1", "user:auth:2");

6. Shiro对权限字符串缺失部分的处理

如“user:view”等价于“user:view:*”;

而“organization”等价于“organization:*”或者“organization:*:*”。

可以这么理解,这种方式实现了前缀匹配。

另外如:

“user:*”可以匹配如“user:delete”

“user:delete”可以匹配如“user:delete:1”

“user:*:1”可以匹配如“user:view:1”、

“user”可以匹配”user:view”或“user:view:1”等。

  • 即*可以匹配所有,不加*可以进行前缀匹配;
  • 但是如“*:view”不能匹配“user:view”,需要使用“*:*:view”;
  • 即后缀匹配必须指定前缀(多个冒号就需要多个*来匹配)。

7. WhildcardPermission

如下两种方式是等价的:

subject.checkPermission("menu:view:1");

subject.checkPermission(new WildcardPermission("menu:view:1"));

8. 性能问题

通配符匹配方式比字符串相等匹配来说是更复杂的,因此需要花费更长时间,但是一般系统的权限不会太多,且可以配合缓存来提供其性能,如果这样性能还达不到要求我们可以实现位操作算法实现性能更好的权限匹配。另外实例级别的权限验证如果数据量太大也不建议使用,可能造成查询权限及匹配变慢。可以考虑比如在sql查询时加上权限字符串之类的方式在查询时就完成了权限匹配。

3.5 授权流程

流程如下:

  • 首先调用Subject.isPermitted*/hasRole* 接口,其会委托给 SecurityManager,而 SecurityManager 接着会委托给 Authorizer;
  • Authorizer 是真正的授权者,如果我们调用如 isPermitted(“user:view”),其首先会通过 PermissionResolver 把字符串转换成相应的 Permission 实例;
  • 在进行授权之前,其会调用相应的 Realm 获取 Subject 相应的角色/权限用于匹配传入的角色/权限;
  • Authorizer 会判断 Realm 的角色/权限是否和传入的匹配,如果有多个 Realm,会委托给 ModularRealmAuthorizer 进行循环判断,如果匹配如isPermitted*/hasRole* 会返回 true,否则返回 false 表示授权失败。

ModularRealmAuthorizer 进行多 Realm 匹配流程:

  • 首先检查相应的 Realm 是否实现了实现了 Authorizer;
  • 如果实现了 Authorizer,那么接着调用其相应的 isPermitted*/hasRole* 接口进行匹配;
  • 如果有一个 Realm 匹配那么将返回 true,否则返回 false。

如果 Realm 进行授权的话,应该继承 AuthorizingRealm,其流程是:

  • 如果调用 hasRole*,则直接获取 AuthorizationInfo.getRoles() 与传入的角色比较即可;首先如果调用如 isPermitted(“user:view”),首先通过 PermissionResolver 将权限字符串转换成相应的 Permission 实例,默认使用 WildcardPermissionResolver,即转换为通配符的 WildcardPermission;
  • 通过 AuthorizationInfo.getObjectPermissions() 得到 Permission 实例集合;通过 AuthorizationInfo.getStringPermissions() 得到字符串集合并通过 PermissionResolver 解析为 Permission 实例;然后获取用户的角色,并通过 RolePermissionResolver 解析角色对应的权限集合(默认没有实现,可以自己提供);
  • 接着调用 Permission.implies(Permission p) 逐个与传入的权限比较,如果有匹配的则返回 true,否则 false。

Authorizer、PermissionResolver及RolePermissionResolver:

Authorizer 的职责是进行授权(访问控制),是 Shiro API 中授权核心的入口点,其提供了相应的角色/权限判断接口,具体请参考其 Javadoc。SecurityManager 继承了 Authorizer 接口,且提供了 ModularRealmAuthorizer 用于多 Realm 时的授权匹配。

PermissionResolver 用于解析权限字符串到 Permission 实例。

RolePermissionResolver 用于根据角色解析相应的权限集合。

我们可以通过如下 ini 配置更改 Authorizer 实现:

authorizer=org.apache.shiro.authz.ModularRealmAuthorizer
securityManager.authorizer=$authorizer

对于 ModularRealmAuthorizer,相应的 AuthorizingSecurityManager 会在初始化完成后自动将相应的 realm 设置进去,我们也可以通过调用其 setRealms() 方法进行设置。对于实现自己的 authorizer 可以参考 ModularRealmAuthorizer 实现即可。

设置 ModularRealmAuthorizer 的 permissionResolver,其会自动设置到相应的 Realm 上(其实现了 PermissionResolverAware 接口),如:

permissionResolver=org.apache.shiro.authz.permission.WildcardPermissionResolver
authorizer.permissionResolver=$permissionResolver

设置 ModularRealmAuthorizer 的 rolePermissionResolver,其会自动设置到相应的 Realm 上(其实现了 RolePermissionResolverAware 接口),如:

rolePermissionResolver=com.ms.MyRolePermissionResolver
authorizer.rolePermissionResolver=$rolePermissionResolver

本文分享自微信公众号 - 码神联盟(lkchatspace)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2018-10-30

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 200行代码,一行行教你自制微信机器人

    1) 用一个windows客户端工具运营公众号,真的很局限。虽然工具的功能很强大,能自动添加好友,自动拉好友入群,关键字回复等等,但是有一个绕不开的点,它是一款...

    用户1634449
  • 猫头鹰的深夜翻译:Pattern: Service Mesh

    在十几年前,我们无法想象一个分布式系统会是什么样子。它给我们带来了全新的架构思路,但同时也引入了一些问题。 当时这些系统非常少有而且架构简单,工程师们通过尽可能...

    眯眯眼的猫头鹰
  • 不可思议,我们程序员竟然上热搜了

    天气转冷,一支神秘而又强大的力量突然重出江湖。他们是一群思维严谨,着装统一(其实就是撞衫),腰别键盘,双肩背包的人。这股神秘而又庞大的力量充斥在江湖的一线和二线...

    非著名程序员
  • 3.2、苏宁百万级商品爬取 思路讲解 商品爬取

    如果我要得到A类别的第B页的商品我应该如何拼接符合条件的地址 我们首先分析地址,地址如下

    小狐狸
  • QQ如何把你消息传递给好友的?(下篇)

    话说你已经成功注册了QQ号码,取名叫“村头小伙”。你的同学小芳“村里那个姑娘”也接受了你的好友申请。之后的日子里面,你们经常通过QQ发送文字和语音,偶尔还会视频...

    张叔叔讲互联网
  • python基础类型(一):字符串和列表

    注意到最后三个的单双引号是嵌套使用的,但是最后一个的使用方法是错误的,因为当我们混合使用两种引号时必须有一种用来划分字符串的边界,即在两边的引号不能出现在字符串...

    渔父歌
  • TFS2018环境搭建一硬件要求

    TFS可以安装在Windows Server和Windows PC操作系统中,但是TFS2018和2018只支持64位操作系统中,早期的版本没有操作系统的位数限...

    郑小超.
  • 当妈妈在淘宝购物的时候,都发生了什么?(下篇)

    在上一篇文章中,讲到了你的妈妈成功从你手中夺得了电脑的控制权,然后打开了淘宝网并且在网站首页搜索框中搜索了“美丽的裙子”,之后用一种挑剔的眼光盯着电脑屏幕一个多...

    张叔叔讲互联网
  • 一些常用的算法技巧总结

    数组的下标是一个隐含的很有用的数组,特别是在统计一些数字,或者判断一些整型数是否出现过的时候。例如,给你一串字母,让你判断这些字母出现的次数时,我们就可以把这些...

    帅地
  • 一张图解释负载均衡

    首先当大量用户访问时候,先请求到nignx服务器,因为nignx对于高并发支持较好,所以由nignx服务器将访问需求分配给不同的apache服务器,apache...

    smy

扫码关注云+社区

领取腾讯云代金券