博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
(六)授权(下):自定义permission
阅读量:5860 次
发布时间:2019-06-19

本文共 6191 字,大约阅读时间需要 20 分钟。

一、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.BitAndWildPermissionResolverauthorizer.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
    resolvePermissionsInRole(String roleString) { if("role1".equals(roleString)) { return Arrays.asList((Permission)new WildcardPermission("menu:*")); } return null; } }
     
  • 自定义Realm.java
public class MyRealm1 extends AuthorizingRealm{    /**     * 判断授权的     */    @Override      protected 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;      }      /**     * 判断认证的     */    @Override    protected 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

你可能感兴趣的文章
PostgreSQL backup and recovery - online logical backup & recovery
查看>>
C++玫瑰
查看>>
如何在Element UI 对话框里面加载高德地图
查看>>
深入理解编译注解(三)依赖关系 apt/annotationProcessor与Provided的区别
查看>>
类似微信首页弹性滚动和惯性滚动效果的实现——OverScroll
查看>>
试读angular源码第一章:开场与platformBrowserDynamic
查看>>
android插件自定义之多渠道打包插件(支持微信资源混淆andResGuard)
查看>>
Win实用好用软件清单推荐
查看>>
一道关于面向对象面试题
查看>>
程序员的商业模式
查看>>
Vue双向绑定实现
查看>>
阿里数据库内核月报:2017年06月
查看>>
使用html5做的环形进度条
查看>>
如何写一份更好的简历
查看>>
web端播放m3u8视频流注意事项
查看>>
http浅析
查看>>
算法基础-希尔排序
查看>>
面试官: css3动画了解吗? 我: .......
查看>>
使用ConcurrentHashMap一定线程安全?
查看>>
【Laravel-海贼王系列】第十七章,Laravel 那些骚操作
查看>>