• shiro授权流程分析


    0前言

    前面认证过程的入口是subject接口的login方法,本节授权也从subject入口开始,授权包含验证角色和权限两部分。

    验证角色

    subject.hasRole(String)     返回true或者false,不会抛异常

    subject.checkRole(String)  失败抛异常

    验证权限

    subject.isPermitted(String) 返回true或者false,不会抛异常

    subject.checkPermission(String)  失败抛异常

    下面是测试的demo

        @Test
        public void testRole() {
    
            Subject subject = login("test", "123");
    
            Assert.assertTrue(subject().hasRole("custom"));
    
            //验证失败会抛异常
            //subject().checkRole("role1");
    
            //退出
            subject.logout();
        }
    
        @Test
        public void testPerm() {
    
            Subject subject = login("test", "123");
    
            Assert.assertTrue(subject().isPermitted("custom:perm"));
    
            //验证失败会抛异常
            //subject().checkPermission("role1");
    
            //退出
            subject.logout();
        }
    
        private Subject login(String username, String password){
    
            //创建SecurityManager实例,配置realm
            org.apache.shiro.mgt.SecurityManager securityManager = new DefaultSecurityManager();
            Realm realm = new MyRealm1();
            ((DefaultSecurityManager) securityManager).setRealm(realm);
    
            //绑定SecurityManager给SecurityUtils
            SecurityUtils.setSecurityManager(securityManager);
    
            //得到Subject
            Subject subject = SecurityUtils.getSubject();
    
            //创建用户名/密码身份验证Token(即用户身份/凭证)
            UsernamePasswordToken token = new UsernamePasswordToken(username, password);
    
            try {
                //登录,即身份验证
                subject.login(token);
            } catch (AuthenticationException e) {
                //身份验证失败处理
                e.printStackTrace();
            }
    
            //断言用户已经登录
            Assert.assertEquals(true, subject.isAuthenticated());
    
            return subject;
        }

    下面是MyRealm1类

    public class MyRealm1 extends AuthorizingRealm {
    
        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
    
            String username = (String)principals.getPrimaryPrincipal();
    
            //模拟根据不同用户名获取不同的角色和权限
            String userRole = "";
            List<String> userPerms = new ArrayList<>();
            if ("test".equals(username)){
                userRole = "custom";
                userPerms.add("custom:perm");
            } else if ("admin".equals(username)){
                userRole = "admin";
                userPerms.add("admin:perm");
            }
    
            SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
            authorizationInfo.addRole(userRole);
            authorizationInfo.addStringPermissions(userPerms);
    
            return authorizationInfo;
        }
    
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
    
            String username = (String)token.getPrincipal();  //得到用户名
            String password = new String((char[])token.getCredentials()); //得到密码
    
            if(!"test".equals(username) && !"admin".equals(username)) {
                throw new UnknownAccountException(); //如果用户名错误
            }
            if(!"123".equals(password)) {
                throw new IncorrectCredentialsException(); //如果密码错误
            }
    
            //如果身份认证验证成功,返回一个AuthenticationInfo实现;
            return new SimpleAuthenticationInfo(username, password, getName());
        }
    }

    1.角色验证

    //DelegatingSubject 第223行
    
        public boolean hasRole(String roleIdentifier) {
            return hasPrincipals() && securityManager.hasRole(getPrincipals(), roleIdentifier);
        }
    //AuthorizingSecurityManager 第152行
    
       public boolean hasRole(PrincipalCollection principals, String roleIdentifier) {
            //SecurityManager 调用Authorizer
            return this.authorizer.hasRole(principals, roleIdentifier);
        }
    //AuthorizingRealm 第570行
    
        public boolean hasRole(PrincipalCollection principal, String roleIdentifier) {
            AuthorizationInfo info = getAuthorizationInfo(principal);
            return hasRole(roleIdentifier, info);
        }
    
    
    // AuthorizingRealm 第310行
        protected AuthorizationInfo getAuthorizationInfo(PrincipalCollection principals) {
    
            if (principals == null) {
                return null;
            }
    
            AuthorizationInfo info = null;
    
            if (log.isTraceEnabled()) {
                log.trace("Retrieving AuthorizationInfo for principals [" + principals + "]");
            }
    
            Cache<Object, AuthorizationInfo> cache = getAvailableAuthorizationCache();
            if (cache != null) {
                if (log.isTraceEnabled()) {
                    log.trace("Attempting to retrieve the AuthorizationInfo from cache.");
                }
                Object key = getAuthorizationCacheKey(principals);
                info = cache.get(key);
                if (log.isTraceEnabled()) {
                    if (info == null) {
                        log.trace("No AuthorizationInfo found in cache for principals [" + principals + "]");
                    } else {
                        log.trace("AuthorizationInfo found in cache for principals [" + principals + "]");
                    }
                }
            }
    
    
            if (info == null) {
                // Call template method if the info was not found in a cache 
    //调用子类doGetAuthrizationInfo方法(参照前面MyRealm1)
    info = doGetAuthorizationInfo(principals); // If the info is not null and the cache has been created, then cache the authorization info. if (info != null && cache != null) { if (log.isTraceEnabled()) { log.trace("Caching authorization info for principals: [" + principals + "]."); } Object key = getAuthorizationCacheKey(principals); cache.put(key, info); } } return info; }
    //AuthorizingRealm 第575行
        protected boolean hasRole(String roleIdentifier, AuthorizationInfo info) {
            return info != null && info.getRoles() != null && info.getRoles().contains(roleIdentifier);
        }

    角色验证,这里只分析了hasRole方法,checkRole方法与之类似,不同的是验证失败会抛出异常。

    总结一下角色验证过程

    (1)用户程序调用subject.hasRole(roleString)

    (2)subject调用SecurityManager的hasRole方法

    (3)SecurityManager通过Authorizer的hasRole方法验证是否拥有角色

    (4)Authorizer类hasRole方法内通过AuthorizingRealm的getAuthorizationInfo获取角色信息

    (5)AuthorizingRealm最后通过调用子类的doGetAuthrizationInfo获取用户角色集合,在通过集合的contains方法判断角色。

    2.权限验证

    todo

  • 相关阅读:
    HDU4758 Walk Through Squares(AC自动机+状压DP)
    HIT2543 Stone IV(一定费用内的最大流)
    HIT2715 Matrix3(最小费用最大流)
    COGS738 [网络流24题] 数字梯形(最小费用最大流)
    HDU3157 Crazy Circuits(有源汇流量有上下界网络的最小流)
    ZOJ3229 Shoot the Bullet(有源汇流量有上下界网络的最大流)
    BZOJ 1834 [ZJOI2010]network 网络扩容(费用流)
    BZOJ 1475 方格取数(二分图最大点权独立集)
    BZOJ 4236 JOIOJI(前缀和)
    HZAU 1201 Friends(树形DP)
  • 原文地址:https://www.cnblogs.com/ouym/p/15621580.html
Copyright © 2020-2023  润新知