一、Authorizer、PermissionResolver及RolePermissionResolver

Authorizer的职责是进行授权(访问控制),是Shiro API中授权核心的入口点,其提供了相应的角色/权限判断接口,具体请参考其Javadoc。SecurityManager继承了Authorizer接口,且提供了ModularRealmAuthorizer用于多Realm时的授权匹配。PermissionResolver用于解析权限字符串到Permission实例,而RolePermissionResolver用于根据角色解析相应的权限集合。

二、案例

  • shiro.ini
[main]
#自定义authorizer
authorizer=org.apache.shiro.authz.ModularRealmAuthorizer
#自定义permissionResolver
#permissionResolver=org.apache.shiro.authz.permission.WildcardPermissionResolver
permissionResolver=servlet.BitAndWildPermissionResolver
authorizer.permissionResolver=$permissionResolver
#自定义rolePermissionResolver
rolePermissionResolver=servlet.MyRolePermissionResolver
authorizer.rolePermissionResolver=$rolePermissionResolver  securityManager.authorizer=$authorizer #自定义realm 一定要放在securityManager.authorizer赋值之后(因为调用setRealms会将realms设置给authorizer,并给各个Realm设置permissionResolver和rolePermissionResolver)
realm=realms.MyRealm1
securityManager.realms=$realm   

  • 对于ModularRealmAuthorizer,相应的AuthorizingSecurityManager会在初始化完成后自动将相应的realm设置进去,我们也可以通过调用其setRealms()方法进行设置
  • BitPermission.java
package servlet;import org.apache.shiro.authz.Permission;/*** BitPermission用于实现位移方式的权限,如规则是:* * 权限字符串格式:+资源字符串+权限位+实例ID;以+开头中间通过+分割;权限:0 表示所有权限;1 新增(二进制:0001)、2* 修改(二进制:0010)、4 删除(二进制:0100)、8 查看(二进制:1000);如 +user+10 表示对资源user拥有修改/查看权限。* * @author Administrator**/
public class BitPermission implements Permission {private String resourceIdentify;private int permissionBit;private String instanceId;public BitPermission(String permissionString) {String[] array = permissionString.split("\\+");if (array.length > 1) {resourceIdentify = array[1];}if (resourceIdentify == null || resourceIdentify.equals("")) {resourceIdentify = "*";}if (array.length > 2) {permissionBit = Integer.valueOf(array[2]);}if (array.length > 3) {instanceId = array[3];}if (instanceId == null || resourceIdentify.equals("")) {instanceId = "*";}}public boolean implies(Permission p) {if (!(p instanceof BitPermission)) {return false;}BitPermission other = (BitPermission) p;if (!("*".equals(this.resourceIdentify) || this.resourceIdentify.equals(other.resourceIdentify))) {return false;}if (!(this.permissionBit == 0 || (this.permissionBit & other.permissionBit) != 0)) {return false;}if (!("*".equals(this.instanceId) || this.instanceId.equals(other.instanceId))) {return false;}return true;}
}

  • BitPermission用于实现位移方式的权限,如规则是:

    权限字符串格式:+资源字符串+权限位+实例ID;以+开头中间通过+分割;权限:0 表示所有权限;1 新增(二进制:0001)、2 修改(二进制:0010)、4 删除(二进制:0100)、8 查看(二进制:1000);如 +user+10 表示对资源user拥有修改/查看权限。

  • Permission接口提供了boolean implies(Permission p)方法用于判断权限匹配的.
  • MyRolePermissionResolver.java:RolePermissionResolver用于根据角色字符串来解析得到权限集合
    public class MyRolePermissionResolver implements RolePermissionResolver {  public Collection<Permission> resolvePermissionsInRole(String roleString) {  if("role1".equals(roleString)) {  return Arrays.asList((Permission)new WildcardPermission("menu:*"));  }  return null;  }
    }   

     
  • 自定义Realm.java
public class MyRealm1 extends AuthorizingRealm{/*** 判断授权的*/@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {  SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();  authorizationInfo.addRole("role1");  authorizationInfo.addRole("role2");  authorizationInfo.addObjectPermission(new BitPermission("+user1+10"));  authorizationInfo.addObjectPermission(new WildcardPermission("user1:*"));  authorizationInfo.addStringPermission("+user2+10");  authorizationInfo.addStringPermission("user2:*");  return authorizationInfo;  }  /*** 判断认证的*/@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {String userName=token.getPrincipal().toString();String passWord=new String((char[])token.getCredentials());if(!userName.equals("zhang")) throw new UnknownAccountException("Realm1 用户名错误");if(!passWord.equals("123")) throw new IncorrectCredentialsException("Realm1 密码错误");return new SimpleAccount(userName, passWord, getName());}}

  • 此次还要注意就是不能把我们自定义的如“+user1+10”配置到INI配置文件,即使有IniRealm完成,因为IniRealm在new完成后就会解析这些权限字符串,默认使用了WildcardPermissionResolver完成,即此处是一个设计权限,如果采用生命周期(如使用初始化方法)的方式进行加载就可以解决我们自定义permissionResolver的问题。
public class TestMain {public static void main(String[] args) {SecurityManager securityManager=new IniSecurityManagerFactory("classpath:shiro.ini").getInstance(); SecurityUtils.setSecurityManager(securityManager);Subject subject=SecurityUtils.getSubject();subject.login(new UsernamePasswordToken("zhang", "123"));//通过二进制位的方式表示权限  System.out.println(subject.isPermitted("+user1+2"));//新增权限  System.out.println(subject.isPermitted("+user1+8"));//查看权限System.out.println(subject.isPermitted("+user2+10"));//新增及查看
  System.out.println(subject.isPermitted("+user1+4"));//没有删除权限  System.out.println(subject.isPermitted("menu:view"));//通过MyRolePermissionResolver解析得到的权限
    }
}

  • 流程如下:

1、首先调用Subject.isPermitted*/hasRole*接口,其会委托给SecurityManager,而SecurityManager接着会委托给Authorizer;

2、Authorizer是真正的授权者,如果我们调用如isPermitted(“user:view”),其首先会通过PermissionResolver把字符串转换成相应的Permission实例;

3、在进行授权之前,其会调用相应的Realm获取Subject相应的角色/权限用于匹配传入的角色/权限;

4、Authorizer会判断Realm的角色/权限是否和传入的匹配,如果有多个Realm,会委托给ModularRealmAuthorizer进行循环判断,如果匹配如isPermitted*/hasRole*会返回true,否则返回false表示授权失败。

 本例中的流程大概是:

1.System.out.println(subject.isPermitted("+user1+2"));
2.BitAndWildPermissionResolver把字符串转换成相应的Permission实例(调用BitPermission的构造方法,参数为"+user1+2",解析该参数并封装到BitPermission的成员变量中,即将该参数转为BitPermission实例)
3.MyRealm1中的doGetAuthorizationInfo方法获取Subject相应的角色/权限用于匹配传入的角色/权限

转载于:https://www.cnblogs.com/shyroke/p/7838115.html

(六)授权(下):自定义permission相关推荐

  1. Spring Security Oauth2 授权码模式下 自定义登录、授权页面

    主要说明:基于若依springcloud微服务框架的2.1版本 嫌弃缩进不舒服的,直接访问我的博客站点: http://binarydance.top//aticle_view.html?aticle ...

  2. spring Cloud微服务 security+oauth2认证授权中心自定义令牌增强,并实现登录和退出

    文章目录 认证授权中心自定义令牌增强 自定义认证端点返回结果 登录逻辑调整,增强令牌返回参数 测试验证 用户微服务构建 配置类构建 相关实体类 登录 退出登录 在之前的博客我写了 SpringClou ...

  3. opensuse-KDE桌面下自定义快捷键,ctrl+alt+t打开konsole

    2019独角兽企业重金招聘Python工程师标准>>> opensuse-KDE桌面下自定义快捷键,ctrl+alt+t打开konsole 转载于:https://my.oschin ...

  4. sdut 3333 数据结构实验之栈与队列六:下一较大值(二)

    数据结构实验之栈与队列六:下一较大值(二) Time Limit: 150MS Memory Limit: 8000KB Submit Statistic Discuss Problem Descri ...

  5. 对象属性结构赋值_(六)面向对象-下

    (六)面向对象-下 关键字:static static 可以用来修饰的结构:主要用来修饰类的内部结构 属性.方法.代码块.内部类 static修饰属性:静态变量(类变量 属性,是否使用static修饰 ...

  6. 数学之美 系列十六 (下)- 不要把所有的鸡蛋放在一个篮子里 最大熵模型

    数学之美 系列十六 (下)- 不要把所有的鸡蛋放在一个篮子里 最大熵模型 我们上次谈到用最大熵模型可以将各种信息综合在一起.我们留下一个问题没有回答,就是如何构造最大熵模型.我们已经所有的最大熵模型都 ...

  7. 数学之美 系列十六 (下)- 不要把所有的鸡蛋放在一个篮子里 最大熵模型...

    数学之美 系列十六 (下)- 不要把所有的鸡蛋放在一个篮子里 最大熵模型 我们上次谈到用最大熵模型可以将各种信息综合在一起.我们留下一个问题没有回答,就是如何构造最大熵模型.我们已经所有的最大熵模型都 ...

  8. 异贝,通过移动互联网技术,为中小微实体企业联盟、线上链接、线上线下自定义营销方案推送。案例62

    欢迎关注异贝.异贝5G营销工具,今天给大家带来的是体育用品店的营销案例: 生命不止,运动不息.许多人都爱运动,爱体育,但随着社会发展,越来越少人会去到传统的体育用品店购买运动用品.一方面原因是电商的发 ...

  9. 异贝,通过移动互联网技术,为中小微实体企业联盟、线上链接、线上线下自定义营销方案推送。案例52

    欢迎关注异贝.异贝5G营销工具,今天给大家带来的案例是小超市的营销方案: 随着经济的不断发展,越来越多的大型企业都看中了四五线县城的人口和消费能力,许多深耕当地的经营场所,都收到了这些"外来 ...

  10. 异贝,通过移动互联网技术,为中小微实体企业联盟、线上链接、线上线下自定义营销方案推送。案例53

    欢迎关注异贝.异贝5G营销工具,今天给大家带来的案例是桌游店的营销方案: 随着娱乐至上的时代来临,各式各样的游戏.项目层出不穷,而其中最火热的闲暇娱乐项目,要数因手游而孕育而生的"剧本杀&q ...

最新文章

  1. Python绘图之matplotlib基础教程:matplotlib库图表绘制中常规设置大全(交互模式、清除原有图像、设置横坐标显示文字/旋转角度、添加图例、绘图布局自动调整、图像显示、图像暂停)
  2. webpack2.x基础属性讲解(二)
  3. node 16位 转24位_C代码实现16位和32位数据字节序转换
  4. Python学习笔记7:函数对象及函数对象作參数
  5. 无线路由与无线AP有什么不同
  6. 用Python写一个简单的监控系统
  7. Oracle中登录OEM口令忘记,oracle oem创建过程 一直提示sys密码错误
  8. 时间序列入门概念整理
  9. android分辨率修改器,安卓分辨率一键修改器
  10. 方立勋_30天掌握JavaWeb_回顾复习
  11. 考研数学常见的函数图像
  12. 08CMS小说搜索型注入 - 漏洞发布 京华志
  13. PHP的常用框架有哪些?
  14. springboot报错:Use of @OneToMany or @ManyToMany targeting an unmapped class:
  15. 程序员会不会英语的差别
  16. 将.fits数据转换为.png图像
  17. MATLAB变声器程序
  18. Servlet.service() for servlet jsp threw exception
  19. 超全软件下载网站和网页(一网一匠)
  20. 通过OpenSSL解析X509证书基本项

热门文章

  1. Atitit 方法运行器methodRunnerV3 方法虚拟机 vm 新特性 java -cp C:\0wkspc\methodRunner\bin -Djava.ext.dirs=
  2. Atitti knn实现的具体四个距离算法 欧氏距离、余弦距离、汉明距离、曼哈顿距离
  3. paip.python pyqt 加载ui 方法使用connect总结attilax
  4. paip.使用JAVASCRIPT开发桌面与WEB程序
  5. paip..net VS2010提示当前上下文中不存在名称的解决
  6. eclipse插件开发流程
  7. (转)投资很难赚到你不信的那份钱︱投资道
  8. Kafka从上手到实践 - 初步认知:MQ系统 | 凌云时刻
  9. 【手写数字识别】基于matlab GUI BP神经网络手写数字识别【含Matlab源码 1118期】
  10. 【图像融合】基于matlab curvelet变换图像融合【含Matlab源码 776期】