zoukankan      html  css  js  c++  java
  • Shiro入门学习之自定义Realm实现授权(五)

    一、自定义Realm授权

      前提:认证通过,查看Realm接口的继承关系结构图如下,要想通过自定义的Realm实现授权,只需继承AuthorizingRealm并重写方法即可

     二、实现过程

    1、新建module,添加如下pom依赖

    <properties>
            <shiro.version>1.4.1</shiro.version>
            <loggingg.version>1.2</loggingg.version>
        </properties>
        <dependencies>
            <dependency>
                <groupId>org.apache.shiro</groupId>
                <artifactId>shiro-core</artifactId>
                <version>${shiro.version}</version>
            </dependency>
            <dependency>
                <groupId>commons-logging</groupId>
                <artifactId>commons-logging</artifactId>
                <version>${loggingg.version}</version>
            </dependency>
        </dependencies>

    2、新建UserRealm类继承AuthorizingRealm,重写方法

    public class UserRealm extends AuthorizingRealm {
        private UserService userService = new UserServiceImpl();
        private RoleService roleService = new RoleServiceImpl();
        private PermissionService permissionService = new PermissionServiceImpl();
    
        /**
         * 做认证
         *
         * @param token
         * @return
         * @throws AuthenticationException
         */
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
            String username = token.getPrincipal().toString();
            System.out.println("自定义Realm:" + username);
            User user = userService.queryUserByUserName(username);
            if (user != null) {
                List<String> roles = roleService.queryRoleByUserName(username);
                List<String> permissions = permissionService.queryPermissionByUserName(username);
                ActivityUser activityUser = new ActivityUser(user, roles, permissions);
                //参数1:可以传任意对象|参数2:数据库中的用户密码|参数3:当前类名
                SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(activityUser, user.getPwd(), this.getName());
                return info;
            } else {
                return null;
            }
        }
    
        //授权方法
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principal) {
            SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
            System.out.println("doGetAuthorizationInfo被回调了");
            //
            Object primaryPrincipal = principal.getPrimaryPrincipal();
            System.out.println(primaryPrincipal);
    
            ActivityUser activityUser = (ActivityUser) principal.getPrimaryPrincipal();
            List<String> roles = activityUser.getRoles();
            if (roles != null && roles.size() > 0) {
                info.addRoles(roles);
            }
            List<String> permissins = activityUser.getPermissins();
            if (permissins!=null&&permissins.size()>0)
            {
                info.addStringPermissions(permissins);
            }
            //判断如果是超级管理员
            //info.addStringPermission("*:*");
            return info;
        }

    3、test类测试方法

    public class TestAuthorizationRealm
    {
        public static void main(String[] args)
        {
            //1.模拟前台传递的用户名和密码
            String username = "zhangsan";
            String password = "123456";
            //2.创建安全管理器的工厂
            Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
            //3.通过安全管理器工厂获取安全管理器
            DefaultSecurityManager securityManager = (DefaultSecurityManager)factory.getInstance();
            //4.创建自定义的Realm
            UserRealm userRealm = new UserRealm();
            //5.设置自定义的Realm
            securityManager.setRealm(userRealm);
            //6.将安全管理器绑定到当前运行环境
            SecurityUtils.setSecurityManager(securityManager);
            //7.从当前环境中获取Subject主体
            Subject subject1 = SecurityUtils.getSubject();
            //8.调用主体的登录方法
            try
            {
                subject1.login(new UsernamePasswordToken(username,password));
                System.out.println("登录成功~");
    
    //            Object principal = subject1.getPrincipal();
    //            System.out.println(principal);
    
            } catch (IncorrectCredentialsException e) {
                System.out.println("密码不正确");
            }catch (UnknownAccountException e) {
                System.out.println("用户名不存在");
            }
    
            boolean role1 = subject1.hasRole("role1");
            boolean role2 = subject1.hasRole("role1");
            System.out.println(role1);
    
            boolean permitted = subject1.isPermitted("user:add");
            System.out.println(permitted);
        }
    }

    三、分析

    1、在进行授权的时候,每进行一次授权都会进行一次回调自定义Realm的doGetAuthorizationInfo方法,验证如下:

    ①在授权方法内部打印日志

     

     ②test类做3次授权,查看控制台如下:

    2、认证时候进行查库,查角色、权限,并封装对象,避免多次调用授权方法导致频繁查库导致性能下降

     

     四、总结

    1、每次进行授权时,就会调用授权方法(通过打印日志可以验证)

    2、避免在授权回调方法中查库而导致性能下降

    3、授权方法参数可以获取到认证方法中放入的第一个任意参数(图中有说明,当然也可以通过subject.getPrincipal()方法获取该参数),所以我采用封装的方式,实现多次调用授权方法时也是同一个对象,避免频繁查库

  • 相关阅读:
    Vsftpd 3.0.2 正式版发布
    Putdb WebBuilder 6.5 正式版本发布
    SoaBox 1.1.6 GA 发布,SOA 模拟环境
    pynag 0.4.6 发布,Nagios配置和插件管理
    Percona Playback 0.4,MySQL 负荷回放工具
    xombrero 1.3.1 发布,微型 Web 浏览器
    Hypertable 0.9.6.4 发布,分布式数据库
    libmemcached 1.0.11 发布
    CryptoHeaven 3.7 发布,安全邮件解决方案
    Android Activity生命周期
  • 原文地址:https://www.cnblogs.com/rmxd/p/11768605.html
Copyright © 2011-2022 走看看