• 【Shiro】SpringBoot集成Shiro权限认证《上》


    基础认识

    Subject

    主体,代表了当前的“用户”,这个用户不一定是一个具体的人,与当前应用交互的任何东西都是主体,如第三方进程、网络爬虫、机器人等,Subject是一个抽象概念,所有的Subject都绑定到SecurityManager,与Subject的所有交互都会委托给SecurityManager,可以把Subject认为是一个门面;SecurityManager才是实际的执行者.

    SecurityManager

    安全管理器,即所有与安全有关的操作都会与SecurityManager进行交互,是Shiro框架的核心,
    管理所有的Subject,类似于Spring MVC的前端控制器DispatcherServlet;

    Realms

    Shiro从Realm中获取安全数据(比如用户、角色、权限),SecurityManager要验证用户身份,
    需要从Realm中获取相应的用户进行比较确定用户是否合法;验证用户角色/权限也需要从Realm获得相应数据进行比较,类似于DataSource,安全数据源;它封装了数据源的连接细节,并在需要时将相关数据提供给Shiro。

    总之:

    用户、权限是通过Realm让开发人员自己注入到SecurityManager,从而让SecurityManager能得到合法的用户以及权限进行判断;

    开始

    创建SpringBoot项目

    依赖引入

    
        <dependency>
            <groupId>org.apache.shirogroupId>
            <artifactId>shiro-spring-boot-starterartifactId>
            <version>1.5.3version>
        dependency>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-webartifactId>
        dependency>
        <dependency>
            <groupId>org.projectlombokgroupId>
            <artifactId>lombokartifactId>
            <optional>trueoptional>
        dependency>
        
        <dependency>
            <groupId>org.apache.shirogroupId>
            <artifactId>shiro-spring-boot-starterartifactId>
            <version>1.5.3version>
        dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    自定义Realm

    public class CustomerRealm extends AuthorizingRealm {
    
        /**
         * 授权逻辑
         * @param principalCollection
         * @return
         */
        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
            System.out.println("执行了=>授权逻辑PrincipalCollection");
            return null;
        }
    
        /**
         * 认证逻辑
         * @param authenticationToken
         * @return
         */
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) {
            System.out.println("执行了=>认证逻辑AuthenticationToken");
            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

    Shiro配置

    • 创建 ShiroFilterFactoryBean
    • 创建 DefaultWebSecurityManager
    • 创建 realm 对象

    基础结构

    @Configuration
    public class ShiroConfig {
        
        /**
         * realm对象
         * @return
         */
        @Bean
        public CustomerRealm myShiroRealm() {
            return null;
        }
    
        /**
         * 权限管理,配置主要是Realm的管理认证
         * @return
         */
        @Bean
        public DefaultWebSecurityManager securityManager() {
           return null;
        }
    
        /**
         * Filter工厂,设置对应的过滤条件和跳转条件
         * @param securityManager
         * @return
         */
        @Bean
        public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
            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
    • 28
    • 29
    • 30
    • 31

    创建Realm 对象

    Realm对象

       /**
         * Realm对象
         * @return
         */
        @Bean
        public CustomerRealm myShiroRealm() {
            return new CustomerRealm();
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    创建DefaultWebSecurityManager

    权限管理,配置主要是Realm的管理认证

     /**
         * 权限管理,配置主要是Realm的管理认证
         * @return
         */
        @Bean
        public DefaultWebSecurityManager securityManager() {
            DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
            securityManager.setRealm(myShiroRealm());
            return securityManager;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    创建 ShiroFilterFactoryBean

    Filter工厂,设置对应的过滤条件和跳转条件

       /**
         * Filter工厂,设置对应的过滤条件和跳转条件
         * @param securityManager
         * @return
         */
        @Bean
        public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
            ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
            //设置安全管理器
            shiroFilterFactoryBean.setSecurityManager(securityManager);
            return shiroFilterFactoryBean;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    登录接口

    创建一个文件夹controller/LoginController.java

    @RestController
    public class LoginController {
        
        @GetMapping("/login")
        public String login(String userName,String passWord) {
            if (StringUtils.isEmpty(userName) || StringUtils.isEmpty(passWord)) {
                return "用户名密码不能为空";
            }
            //用户认证信息
            Subject subject = SecurityUtils.getSubject();
            UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(userName, passWord);
            try {
                subject.login(usernamePasswordToken);
            } catch (UnknownAccountException e) {
                return "用户不存在";
            } catch (AuthenticationException e) {
                return "用户名密码错误";
            } catch (AuthorizationException e) {
                return "无权限登录";
            }
            return "登录成功";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    修改过滤条件以及认证逻辑

    过滤条件

    修改ShiroConfig中的过滤工厂,设置所有的请求都需要认证,放行登录请求。

    注意:

    这里有一些shiro内置的过滤请求,如下所示:

    • anon:无需认证就可以访问
    • authc:必须认证才可以访问
    • user:必须有“记住我”功能才能使用
    • perms:拥有对某个资源的权限才能访问
    • role:拥有某个角色权限才能访问
    /**
         * Filter工厂,设置对应的过滤条件和跳转条件
         *
         * @param securityManager
         * @return
         */
        @Bean
        public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
            ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
            //设置安全管理器
            shiroFilterFactoryBean.setSecurityManager(securityManager);
            Map<String, String> map = new HashMap<>();
            //对所有用户认证
            map.put("/**", "authc");
            //登录
            shiroFilterFactoryBean.setLoginUrl("/login");
            shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
            return shiroFilterFactoryBean;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    认证逻辑

    shiro会自动帮我们去比对用户名和密码

    在这里,定义了userName 和 passWord ,后续连接数据库后,这里应该是需要通过查询数据库。

     protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) {
            System.out.println("执行了=>认证逻辑AuthenticationToken");
            String userName = "admin";
            String passWord = "123456";
            //这里验证authenticationToken和simpleAuthenticationInfo的信息
         
            return  new SimpleAuthenticationInfo(userName, passWord, getName());
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    到这里,我们可以启动我们工程,访问登录接口,测试一番了。

    访问地址:http://localhost:8080/login -> 用户名密码不能为空
    访问地址:http://localhost:8080/login?userName=wang&passWord=111 -> 用户名密码错误
    访问地址: http://localhost:8080/login?userName=admin&passWord=123456 -> 登录成功

    到这里,暂时结束了。下一章,会连接数据库,完成登录及权限认证相关操作。

  • 相关阅读:
    Python编程笔记
    Vue2:组件进阶
    【紧急情况】:回宿舍放下书包的我,花了20分钟敲了一个抢购脚本
    【JVM】JVM相关机制
    腾讯云 BI 数据分析与可视化的快速入门指南
    在线文本数字识别列表求和工具
    Java中的super关键字
    mysql8 MGR集群部署
    【LLM大模型】大模型也内卷,Vicuna训练及推理指南,效果碾压斯坦福羊驼
    Docker基本配置及使用
  • 原文地址:https://blog.csdn.net/Java_Wxlin/article/details/133345078