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()方法获取该参数),所以我采用封装的方式,实现多次调用授权方法时也是同一个对象,避免频繁查库

  • 相关阅读:
    Linux 文件排序
    ubuntu18.04 美化桌面
    git clone 加速
    ubunutu下图像编辑器安装
    vue.js实战教程 https://www.jb51.net/Special/978.htm
    原生JS实现多条件筛选
    php结合js实现多条件组合查询
    js前端 多条件筛选查询
    JS 判断字符串是否全部为数字
    GET请求中URL的最大长度限制总结
  • 原文地址:https://www.cnblogs.com/rmxd/p/11768605.html
Copyright © 2011-2022 走看看