• Springboot集成Shiro完成认证授权


    Apache Shiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码和会话管理。使用Shiro的易于理解的API,您可以快速、轻松地获得任何应用程序,从最小的移动应用程序到最大的网络和企业应用程序。

    三个核心组件:Subject, SecurityManager 和 Realms.
    在这里插入图片描述
    Subject: 即“当前操作用户”。但是,在Shiro中,Subject这一概念并不仅仅指人,也可以是第三方进程、后台帐户(Daemon Account)或其他类似事物。它仅仅意味着“当前跟软件交互的东西”。但考虑到大多数目的和用途,你可以把它认为是Shiro的“用户”概念。Subject代表了当前用户的安全操作,SecurityManager则管理所有用户的安全操作。

    SecurityManager: 它是Shiro框架的核心,典型的Facade模式,Shiro通过SecurityManager来管理内部组件实例,并通过它来提供安全管理的各种服务。

    Realm: Realm充当了Shiro与应用安全数据间的“桥梁”或者“连接器”。也就是说,当对用户执行认证(登录)和授权(访问控制)验证时,Shiro会从应用配置的Realm中查找用户及其权限信息。从这个意义上讲,Realm实质上是一个安全相关的DAO:它封装了数据源的连接细节,并在需要时将相关数据提供给Shiro。当配置Shiro时,你必须至少指定一个Realm,用于认证和(或)授权。配置多个Realm是可以的,但是至少需要一个。
      Shiro内置了可以连接大量安全数据源(又名目录)的Realm,如LDAP、关系数据库(JDBC)、类似INI的文本配置资源以及属性文件等。如果缺省的Realm不能满足需求,你还可以插入代表自定义数据源的自己的Realm实现。

    一.thymeleaf模板的导入

    1.引入依赖:

    
        org.springframework.boot
        spring-boot-starter-thymeleaf
                    
    
    • 1
    • 2
    • 3
    • 4

    2.在controller中添加测试方法

    @RequestMapping("/testThymeleaf")
     public String testThymeleaf(ModelMap model){
         model.addAttribute("name","李国辉");
         //返回test.html
         return "test";
     }
        
    创建一个简单的test.html,然后获取name的值
    
     
     
         
         Title
     
     
         

    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    二 .Shiro实践

    2.1 分析Shiro的核心API

    Subject: 用户主体(把操作交给SecurityManager)
    SecurityManager: 安全管理器 (关联Realm)
    Realm: Shiro连接数据的桥梁
    
    • 1
    • 2
    • 3

    2.2 导入shiro与spring整合依赖

    修改pom.xml,导入依赖
    
        org.apache.shiro
        shiro-spring
        1.4.0
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    2.3 自定义Realm类:

    public class UserRealm extends AuthorizingRealm{
    
        /**
         *  执行授权逻辑
         *
         * @param principals
         * @return
         */
        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
            System.out.println("执行授权逻辑!");
            return null;
        }
    
        /**
         *  执行认证逻辑
         *
         * @param token
         * @return
         * @throws AuthenticationException
         */
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
            System.out.println("执行认证逻辑!");
            return null;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    2.4 编写Shiro的配置类 (*)

    @Configuration
    public class ShiroConfig {
    
        /**
         *  创建ShiroFilterFactoryBean
         */
        public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager securityManager){
    
            ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
            //1.设置安全管理器
            shiroFilterFactoryBean.setSecurityManager(securityManager);
    
            return shiroFilterFactoryBean;
        }
    
        /**
         *  创建DefaultWebSecurityManager
         *  使用@Qualifier注解从Apring容器中引入UserRealm
         */
        @Bean(name = "securityManager")
        public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
            DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
            //关联realm
            securityManager.setRealm(userRealm);
            return securityManager;
        }
    
        /**
         *  创建Realm对象
         *  加载到spring容器中共其他方法调用
         */
    
        @Bean(name ="userRealm")
        public UserRealm getRealm(){
            return new UserRealm();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    2.5 编写Controller登录逻辑

        @RequestMapping("login")
        public String login(String name,String password,ModelMap model){
            /**
             *  使用Shiro编写认证操作
             */
            //1. 获取Subject
            Subject subject = SecurityUtils.getSubject();
            //2.封装用户数据
            UsernamePasswordToken token = new UsernamePasswordToken(name, password);
            //执行登录方法
            try{
                subject.login(token);
                //登录成功! 跳转到test.html
                return "redirect:/thymeleaf";
    
            }catch (UnknownAccountException e){
                //登录失败!直接掉到login.html页面
                model.addAttribute("msg","用户名不存在!");
                return "login";
            }catch (IncorrectCredentialsException e){
                //登录失败,密码错误
                model.addAttribute("msg","密码错误!");
                return "login";
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    2.6 判断Realm的判断逻辑

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        System.out.println("执行认证逻辑!");
        //模拟数据库中的用户名和密码
        String username = "aaa";
        String password = "123456";
        //编写Shiro的判断逻辑,判断用户名和密码
        UsernamePasswordToken token1 = (UsernamePasswordToken) token;
        //判断用户名
        if(!token1.getUsername().equals(username)){
            //用户名不存在!
            return null; //Shiro底层会抛出UnKnowAccountException
        }
        //判断密码
        return new SimpleAuthenticationInfo("",password,"");
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    三.整合mybatis实现登录

    3.1 导入相关依赖:

    
      com.alibaba
        druid
        1.0.25
    
    
        mysql
        mysql-connector-java
    
    
        org.mybatis.spring.boot
        mybatis-spring-boot-starter
        1.3.2
    
        		
        生成相应的实体类,具体的插件都在pom文件找那个进行插入
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    3.2 编写service通过用户名查询对象接口:

    @Override
    public User selectUserByName(String name) {
        UserExample example = new UserExample();
        example.createCriteria().andNameEqualTo(name);
        List users = userMapper.selectByExample(example);
        if(users.isEmpty()){
            return null;
        }else {
            return users.get(0);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    注意:在启动类中加入@MapperScan注解进行mapper扫描,不然启动不起来

    3.3 在userRealm中注入userService,并进行代码改造

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        System.out.println("执行认证逻辑!");
        //编写Shiro的判断逻辑,判断用户名和密码
        UsernamePasswordToken token1 = (UsernamePasswordToken) token;
        //通过登录传过来的用户名查询数据库中的用户是否存在!
        User user = userService.selectUserByName(token1.getUsername());
        //判断用户名
        if(user==null){
            //用户名不存在!
            return null; //Shiro底层会抛出UnKnowAccountException Controller中进行捕获
        }
        //判断密码
        return new SimpleAuthenticationInfo("",user.getPassword(),"");
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    四.Springboot与Shiro整合实现用户授权

    4.1 使用Shiro内置过滤器拦截资源

    1).在shiroConfig中对接口添加需要授权
        /**
         *  为add接口添加授权过滤器
         *  注意: 当授权拦截后,shiro会自动跳转到未授权页面
         */
        map.put("/add","perms[user:add]");  
    2). 设置未授权提示页面
        //设置未授权提示页面
        shiroFilterFactoryBean.setUnauthorizedUrl("/unAuth"); //跳转到的controller接口  
    3). 编写跳转接口以及接口中定义跳转的页面
        @RequestMapping("unAuth")
        public String unAuth(){
            return "user/unAuth";
        }  
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    4.2 动态授权逻辑编写:

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        System.out.println("执行授权逻辑!");
        //给资源进行授权
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        //添加授权字符串,就是在shiroConfig中授权时定义的字符串
        //到数据库中查询当前登录用户的授权字符串
        //获取当前用户
        Subject subject = SecurityUtils.getSubject();
        //要想获取到当前用户,需要在下面的认证逻辑完成传过来
    
        User user = (User) subject.getPrincipal();
          User dbUser = userService.selectUserById(user.getId());
    
          //然后添加授权字符串
          info.addStringPermission(dbUser.getPerms());
      //  info.addStringPermission("user:add");
     //   info.addStringPermissions();  添加一个集合
          return info;
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    注意: 要在认证逻辑中把user对象传过来,不然不知道是谁登录,然后就是在shiroconfig中给add和update加上授权拦截

    五.thymeleaf和shiro标签整合使用

    5.1 导入依赖

    
    
        com.github.theborakompanioni
        thymeleaf-extras-shiro
        2.0.0
            
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    5.2 配置ShiroDialect

    在ShiroConfig中进行配置:
     /**
       *  配置ShiroDialect,用于thymeleaf和shiro标签配合使用
       */
      @Bean
      public ShiroDialect getShiroDialect(){
          return new ShiroDialect();
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    前端只需要加上判断即可:但是访问必须要先走登录接口toLogin

     
    用户添加功能: 用户添加
    用户修改功能: 用户修改
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    实现效果展示:

    用户: ligh 密码: 123456 拥有权限: 添加权限

    在这里插入图片描述
    登录成功之后:
    在这里插入图片描述
    点进去进行添加功能:

    在这里插入图片描述
    另外一个用户: liguohui 密码: 123456 权限: 修改权限

    在这里插入图片描述
    登录成功之后:

    在这里插入图片描述
    因为该用户只有修改权限,所以只会显示修改按钮,并且点进去执行修改操作:
    在这里插入图片描述

    至此,Sprignboot集成Shiro完成了认证授权的过程。

  • 相关阅读:
    126. 单词接龙 II BFS
    Android实现在activity启动时传递对象和字符串参数
    YOLOv5、v7改进之三十三:引入GAMAttention注意力机制
    C++ Qt QMainWindow实现无边框窗口自定义标题栏可拖拽移动拉伸改变窗口大小
    [MAUI 项目实战] 手势控制音乐播放器(一): 概述与架构
    Kafka
    Linux常用命令知识点大全(1)
    myeclipse 恢复默认工作布局
    【模型训练】YOLOv7飞鸟检测
    【服务器数据恢复】LINUX误删除、误格式化的数据恢复
  • 原文地址:https://blog.csdn.net/m0_54883970/article/details/126515980