(六)授权(下):自定义permission
一、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相关推荐
- Spring Security Oauth2 授权码模式下 自定义登录、授权页面
主要说明:基于若依springcloud微服务框架的2.1版本 嫌弃缩进不舒服的,直接访问我的博客站点: http://binarydance.top//aticle_view.html?aticle ...
- spring Cloud微服务 security+oauth2认证授权中心自定义令牌增强,并实现登录和退出
文章目录 认证授权中心自定义令牌增强 自定义认证端点返回结果 登录逻辑调整,增强令牌返回参数 测试验证 用户微服务构建 配置类构建 相关实体类 登录 退出登录 在之前的博客我写了 SpringClou ...
- opensuse-KDE桌面下自定义快捷键,ctrl+alt+t打开konsole
2019独角兽企业重金招聘Python工程师标准>>> opensuse-KDE桌面下自定义快捷键,ctrl+alt+t打开konsole 转载于:https://my.oschin ...
- sdut 3333 数据结构实验之栈与队列六:下一较大值(二)
数据结构实验之栈与队列六:下一较大值(二) Time Limit: 150MS Memory Limit: 8000KB Submit Statistic Discuss Problem Descri ...
- 对象属性结构赋值_(六)面向对象-下
(六)面向对象-下 关键字:static static 可以用来修饰的结构:主要用来修饰类的内部结构 属性.方法.代码块.内部类 static修饰属性:静态变量(类变量 属性,是否使用static修饰 ...
- 数学之美 系列十六 (下)- 不要把所有的鸡蛋放在一个篮子里 最大熵模型
数学之美 系列十六 (下)- 不要把所有的鸡蛋放在一个篮子里 最大熵模型 我们上次谈到用最大熵模型可以将各种信息综合在一起.我们留下一个问题没有回答,就是如何构造最大熵模型.我们已经所有的最大熵模型都 ...
- 数学之美 系列十六 (下)- 不要把所有的鸡蛋放在一个篮子里 最大熵模型...
数学之美 系列十六 (下)- 不要把所有的鸡蛋放在一个篮子里 最大熵模型 我们上次谈到用最大熵模型可以将各种信息综合在一起.我们留下一个问题没有回答,就是如何构造最大熵模型.我们已经所有的最大熵模型都 ...
- 异贝,通过移动互联网技术,为中小微实体企业联盟、线上链接、线上线下自定义营销方案推送。案例62
欢迎关注异贝.异贝5G营销工具,今天给大家带来的是体育用品店的营销案例: 生命不止,运动不息.许多人都爱运动,爱体育,但随着社会发展,越来越少人会去到传统的体育用品店购买运动用品.一方面原因是电商的发 ...
- 异贝,通过移动互联网技术,为中小微实体企业联盟、线上链接、线上线下自定义营销方案推送。案例52
欢迎关注异贝.异贝5G营销工具,今天给大家带来的案例是小超市的营销方案: 随着经济的不断发展,越来越多的大型企业都看中了四五线县城的人口和消费能力,许多深耕当地的经营场所,都收到了这些"外来 ...
- 异贝,通过移动互联网技术,为中小微实体企业联盟、线上链接、线上线下自定义营销方案推送。案例53
欢迎关注异贝.异贝5G营销工具,今天给大家带来的案例是桌游店的营销方案: 随着娱乐至上的时代来临,各式各样的游戏.项目层出不穷,而其中最火热的闲暇娱乐项目,要数因手游而孕育而生的"剧本杀&q ...
最新文章
- Python绘图之matplotlib基础教程:matplotlib库图表绘制中常规设置大全(交互模式、清除原有图像、设置横坐标显示文字/旋转角度、添加图例、绘图布局自动调整、图像显示、图像暂停)
- webpack2.x基础属性讲解(二)
- node 16位 转24位_C代码实现16位和32位数据字节序转换
- Python学习笔记7:函数对象及函数对象作參数
- 无线路由与无线AP有什么不同
- 用Python写一个简单的监控系统
- Oracle中登录OEM口令忘记,oracle oem创建过程 一直提示sys密码错误
- 时间序列入门概念整理
- android分辨率修改器,安卓分辨率一键修改器
- 方立勋_30天掌握JavaWeb_回顾复习
- 考研数学常见的函数图像
- 08CMS小说搜索型注入 - 漏洞发布 京华志
- PHP的常用框架有哪些?
- springboot报错:Use of @OneToMany or @ManyToMany targeting an unmapped class:
- 程序员会不会英语的差别
- 将.fits数据转换为.png图像
- MATLAB变声器程序
- Servlet.service() for servlet jsp threw exception
- 超全软件下载网站和网页(一网一匠)
- 通过OpenSSL解析X509证书基本项
热门文章
- Atitit 方法运行器methodRunnerV3 方法虚拟机 vm 新特性 java -cp C:\0wkspc\methodRunner\bin -Djava.ext.dirs=
- Atitti knn实现的具体四个距离算法 欧氏距离、余弦距离、汉明距离、曼哈顿距离
- paip.python pyqt 加载ui 方法使用connect总结attilax
- paip.使用JAVASCRIPT开发桌面与WEB程序
- paip..net VS2010提示当前上下文中不存在名称的解决
- eclipse插件开发流程
- (转)投资很难赚到你不信的那份钱︱投资道
- Kafka从上手到实践 - 初步认知:MQ系统 | 凌云时刻
- 【手写数字识别】基于matlab GUI BP神经网络手写数字识别【含Matlab源码 1118期】
- 【图像融合】基于matlab curvelet变换图像融合【含Matlab源码 776期】