• shiro


    基本概念

    shiro官网

    十分钟快速入门

    Apache Shiro 是 Java 的一个安全框架。对比 Spring Security,可能没有 Spring Security 做的功能强大,但是在实际工作时可能并不需要那么复杂的东西,所以使用小而简单的 Shiro 就足够了。

    Shiro 可以帮助我们完成:认证、授权、加密、会话管理、与 Web 集成、缓存等。

    img

    • Authentication:身份认证 / 登录,验证用户是不是拥有相应的身份;
    • Authorization:授权,即权限验证,验证某个已认证的用户是否拥有某个权限;即判断用户是否能做事情,常见的如:验证某个用户是否拥有某个角色。或者细粒度的验证某个用户对某个资源是否具有某个权限;
    • Session Management:会话管理,即用户登录后就是一次会话,在没有退出之前,它的所有信息都在会话中;会话可以是普通 JavaSE 环境的,也可以是如 Web 环境的;
    • Cryptography:加密,保护数据的安全性,如密码加密存储到数据库,而不是明文存储;
    • Web Support:Web 支持,可以非常容易的集成到 Web 环境;
    • Caching:缓存,比如用户登录后,其用户信息、拥有的角色 / 权限不必每次去查,这样可以提高效率;
    • Concurrency:shiro 支持多线程应用的并发验证,即如在一个线程中开启另一个线程,能把权限自动传播过去;
    • Testing:提供测试支持;
    • Run As:允许一个用户假装为另一个用户(如果他们允许)的身份进行访问;
    • Remember Me:记住我,这个是非常常见的功能,即一次登录后,下次再来的话不用登录了。

    shiro工作流程

    img

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

    SecurityManager:安全管理器;即所有与安全有关的操作都会与 SecurityManager 交互;且它管理着所有 Subject;可以看出它是 Shiro 的核心,它负责与后边介绍的其他组件进行交互,如果学习过 SpringMVC,你可以把它看成 DispatcherServlet 前端控制器;

    Realm:域,Shiro 从 Realm 获取安全数据(如用户、角色、权限),就是说 SecurityManager 要验证用户身份,那么它需要从 Realm 获取相应的用户进行比较以确定用户身份是否合法;也需要从 Realm 得到用户相应的角色 / 权限进行验证用户是否能进行操作;可以把 Realm 看成 DataSource,即安全数据源。

    也就是说对于我们而言,最简单的一个 Shiro 应用:

    1. 应用代码通过 Subject 来进行认证和授权,而 Subject 又委托给 SecurityManager;
    2. 我们需要给 Shiro 的 SecurityManager 注入 Realm,从而让 SecurityManager 能得到合法的用户及其权限进行判断。

    springboot 整合shiro

    1、添加依赖

    <dependency>
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-spring-boot-starter</artifactId>
    </dependency>
    
    • 1
    • 2
    • 3
    • 4

    2、基本配置

    创建xxxRealm对象,继承AuthorizingRealm

    @Component
    public class OAuth2Realm extends AuthorizingRealm {
        @Autowired
        private ShiroService shiroService;
    
        @Override
        public boolean supports(AuthenticationToken token) {
            return token instanceof OAuth2Token;
        }
    
        /**
         * 授权(验证权限时调用)
         */
        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
            SysUserEntity user = (SysUserEntity)principals.getPrimaryPrincipal();
            Long userId = user.getUserId();
    
            //用户权限列表
            Set<String> permsSet = shiroService.getUserPermissions(userId);
    
            SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
            info.setStringPermissions(permsSet);
            return info;
        }
    
        /**
         * 认证(登录时调用)
         */
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
            String accessToken = (String) token.getPrincipal();
    
            //根据accessToken,查询用户信息
            SysUserTokenEntity tokenEntity = shiroService.queryByToken(accessToken);
            //token失效
            if(tokenEntity == null || tokenEntity.getExpireTime().getTime() < System.currentTimeMillis()){
                throw new IncorrectCredentialsException("token失效,请重新登录");
            }
    
            //查询用户信息
            SysUserEntity user = shiroService.queryUser(tokenEntity.getUserId());
            //账号锁定
            if(user.getStatus() == 0){
                throw new LockedAccountException("账号已被锁定,请联系管理员");
            }
    
            SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, accessToken, getName());
            return info;
        }
    }
    
    • 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
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    /**
     * Shiro配置
     *
     * @author Mark sunlightcs@gmail.com
     */
    @Configuration
    public class ShiroConfig {
    
        @Bean("securityManager")
        public SecurityManager securityManager(OAuth2Realm oAuth2Realm) {
            DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
            securityManager.setRealm(oAuth2Realm);
            securityManager.setRememberMeManager(null);
            return securityManager;
        }
    
        @Bean("shiroFilter")
        public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
            ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
            shiroFilter.setSecurityManager(securityManager);
    
            //oauth过滤
            Map<String, Filter> filters = new HashMap<>();
            filters.put("oauth2", new OAuth2Filter());
            shiroFilter.setFilters(filters);
    
            Map<String, String> filterMap = new LinkedHashMap<>();
            filterMap.put("/webjars/**", "anon");
            filterMap.put("/druid/**", "anon");
            filterMap.put("/app/**", "anon");
            filterMap.put("/sys/login", "anon");
            filterMap.put("/swagger/**", "anon");
            filterMap.put("/v2/api-docs", "anon");
            filterMap.put("/swagger-ui.html", "anon");
            filterMap.put("/swagger-resources/**", "anon");
            filterMap.put("/captcha.jpg", "anon");
            filterMap.put("/aaa.txt", "anon");
            filterMap.put("/**", "oauth2");
            shiroFilter.setFilterChainDefinitionMap(filterMap);
    
            return shiroFilter;
        }
    
        @Bean("lifecycleBeanPostProcessor")
        public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
            return new LifecycleBeanPostProcessor();
        }
    
        @Bean
        public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
            AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
            advisor.setSecurityManager(securityManager);
            return advisor;
        }
    
    }
    
    • 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
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
  • 相关阅读:
    Android Material Design之Chip, ChipGroup(十二)
    SAP PI/PO 视频,自己录制
    风控知多点|模型是哪些内容出现了变动才需要重新迭代调整?
    一起看 I/O | Flutter 休闲游戏工具包发布
    PHP 5 MySQLi 函数
    代码随想录9——字符串:KMP算法求解28.实现strStr()
    代码随想录day31|开始贪心咯|贪心理论|455.分发饼干|376. 摆动序列|53. 最大子序和|复习day2|Golang
    Python基础(一) | Python的基本语法
    服务器网站崩溃怎么解决
    (附源码)计算机毕业设计SSM基于的服装商城系统
  • 原文地址:https://blog.csdn.net/qq_43554997/article/details/125501791