• Shiro 使用 JWT Token 配置类参考


    项目中使用了 Shiro 进行验证和授权,下面是 Shiro 配置类给予参考。

    后来并没有使用 Shiro,感觉使用 JWT 还是自己写拦截器比较灵活,使用 Shiro 后各种地方需要魔改,虽然功能也能实现,但感觉把简单问题复杂化了,如果单单只使用 Shiro 授权这一块可以尝试。

    package com.nwgdk.ums.config.shiro;
    
    import com.nwgdk.ums.config.shiro.filter.AccessTokenFilter;
    import com.nwgdk.ums.config.shiro.listener.CustomSessionListener;
    import com.nwgdk.ums.config.shiro.realm.AdminRealm;
    import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
    import org.apache.shiro.mgt.DefaultSubjectDAO;
    import org.apache.shiro.mgt.SecurityManager;
    import org.apache.shiro.session.SessionListener;
    import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
    import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
    import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
    import org.apache.shiro.web.mgt.DefaultWebSessionStorageEvaluator;
    import org.apache.shiro.web.servlet.SimpleCookie;
    import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
    import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.boot.autoconfigure.AutoConfigureAfter;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.DependsOn;
    
    import javax.servlet.Filter;
    import java.util.*;
    
    /**
     * @author nwgdk
     */
    @Configuration
    @AutoConfigureAfter(ShiroLifecycleBeanPostProcessorConfiguartion.class)
    public class ShiroConfiguration {
    
        /**
         * Hash迭代次数
         */
        @Value("${ums.config.hash.hash-iterations}")
        private Integer hashIterations;
    
        /**
         * WEB 过滤器链
         */
        @Bean(name = "shiroFilter")
        public ShiroFilterFactoryBean shiroFilterFactoryBean() {
            ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
            // 设置安全管理器
            shiroFilterFactoryBean.setSecurityManager(securityManager());
            // 注册自定义过滤器
            Map<String, Filter> filterMap = new LinkedHashMap<>(8);
            filterMap.put("authc", new AccessTokenFilter());
            shiroFilterFactoryBean.setFilters(filterMap);
            // 定义过滤链
            Map<String, String> filterChains = new LinkedHashMap<>(8);
            filterChains.put("/v1/admin/login", "anon");
            filterChains.put("/**", "authc");
            // 设置过滤器链
            shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChains);
            return shiroFilterFactoryBean;
        }
    
        /**
         * 安全管理器
         */
        @Bean
        public SecurityManager securityManager() {
            DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
            // 设置 Session 管理器
            securityManager.setSessionManager(sessionManager());
            // 设置 Realm
            securityManager.setRealm(adminRealm());
            // 关闭 RememberMe
            securityManager.setRememberMeManager(null);
            // 设置自定义 Subject
            securityManager.setSubjectFactory(statelessDefaultSubjectFactory());
            // 设置 SubjectDao
            securityManager.setSubjectDAO(defaultSubjectDAO());
            return securityManager;
        }
    
        /**
         * 自定义 Subject 工厂, 禁止使用 Session
         */
        @Bean("subjectFactory")
        public StatelessDefaultSubjectFactory statelessDefaultSubjectFactory() {
            return new StatelessDefaultSubjectFactory();
        }
    
        @Bean
        public DefaultSubjectDAO defaultSubjectDAO() {
            DefaultSubjectDAO subjectDAO = new DefaultSubjectDAO();
            // 设置会话存储调度器
            subjectDAO.setSessionStorageEvaluator(defaultWebSessionStorageEvaluator());
            return subjectDAO;
        }
    
        /**
         * 会话存储器
         */
        @Bean
        public DefaultWebSessionStorageEvaluator defaultWebSessionStorageEvaluator() {
            DefaultWebSessionStorageEvaluator evaluator = new DefaultWebSessionStorageEvaluator();
            // 禁用会话存储
            evaluator.setSessionStorageEnabled(false);
            return evaluator;
        }
    
        /**
         * Session 管理器
         */
        @Bean
        public DefaultWebSessionManager sessionManager() {
            DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
            // 设置 Cookie
            sessionManager.setSessionIdCookie(simpleCookie());
            // 启用 Session Id Cookie,默认启用
            sessionManager.setSessionIdCookieEnabled(false);
            // 设置全局超时时间,默认30分钟
            sessionManager.setGlobalSessionTimeout(1800000L);
            // 设置会话监听器
            sessionManager.setSessionListeners(customSessionListener());
            // 禁用 Session 验证调度器
            sessionManager.setSessionValidationSchedulerEnabled(false);
            return sessionManager;
        }
    
        /**
         * 会话监听器
         */
        @Bean
        public Collection<SessionListener> customSessionListener() {
            List<SessionListener> listeners = new ArrayList<>();
            listeners.add(new CustomSessionListener());
            return listeners;
        }
    
        /**
         * Session Cookie
         */
        @Bean
        public SimpleCookie simpleCookie() {
            SimpleCookie cookie = new SimpleCookie();
            // Session Cookie 名称
            cookie.setName("SID");
            // Session 存活时间
            cookie.setMaxAge(10);
            // 设置 Cookie 只读
            cookie.setHttpOnly(true);
            return cookie;
        }
    
        /**
         * 凭证匹配器
         */
        @Bean("credentialsMatcher")
        public HashedCredentialsMatcher hashedCredentialsMatcher() {
            HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
            // 散列算法
            hashedCredentialsMatcher.setHashAlgorithmName("md5");
            // 散列次数
            hashedCredentialsMatcher.setHashIterations(hashIterations);
            // 使用 HEX 编码
            hashedCredentialsMatcher.setStoredCredentialsHexEncoded(true);
            return hashedCredentialsMatcher;
        }
    
        /**
         * 领域对象
         */
        @Bean("adminRealm")
        public AdminRealm adminRealm() {
            AdminRealm adminRealm = new AdminRealm();
            // 设置密码匹配器
            adminRealm.setCredentialsMatcher(hashedCredentialsMatcher());
            return adminRealm;
        }
    
        /**
         * 开启注解 (如 @RequiresRoles, @RequiresPermissions),
         * 需借助 SpringAOP 扫描使用 Shiro 注解的类,并在必要时进行安全逻辑验证
         * 配置以下两个 Bean:
         * DefaultAdvisorAutoProxyCreator(可选) 和 AuthorizationAttributeSourceAdvisor 即可实现此功能
         */
        @Bean
        @DependsOn({"lifecycleBeanPostProcessor"})
        public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator() {
            DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
            advisorAutoProxyCreator.setProxyTargetClass(true);
            return advisorAutoProxyCreator;
        }
    
        @Bean
        public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor() {
            AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
            authorizationAttributeSourceAdvisor.setSecurityManager(securityManager());
            return authorizationAttributeSourceAdvisor;
        }
    }
    
    package com.nwgdk.ums.config.shiro;
    
    import org.apache.shiro.spring.LifecycleBeanPostProcessor;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    /**
     * @author nwgdk
     */
    @Configuration
    public class ShiroLifecycleBeanPostProcessorConfiguartion {
    
        /**
         * Shiro 生命周期处理器
         */
        @Bean(name = "lifecycleBeanPostProcessor")
        public LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
            return new LifecycleBeanPostProcessor();
        }
    }
    
    package com.nwgdk.ums.config.shiro;
    
    import org.apache.shiro.subject.Subject;
    import org.apache.shiro.subject.SubjectContext;
    import org.apache.shiro.web.mgt.DefaultWebSubjectFactory;
    
    /**
     * 自定义 Subject
     *
     * @author nwgdk
     */
    public class StatelessDefaultSubjectFactory extends DefaultWebSubjectFactory {
        @Override
        public Subject createSubject(SubjectContext context) {
            // 禁止 Subject 创建会话
            context.setSessionCreationEnabled(false);
            return super.createSubject(context);
        }
    }
    
  • 相关阅读:
    Server Tomcat v8.0 Server at localhost was unable to start within 45 seconds. If the server requires more time, try increasing the timeout in the server editor.
    用户画像——“打标签”
    python replace函数替换无效问题
    python向mysql插入数据一直报TypeError: must be real number,not str
    《亿级用户下的新浪微博平台架构》读后感
    【2-10】标准 2 维表问题
    【2-8】集合划分问题(给定要分成几个集合)
    【2-7】集合划分问题
    【2-6】排列的字典序问题
    【2-5】有重复元素的排列问题
  • 原文地址:https://www.cnblogs.com/nwgdk/p/11116328.html
Copyright © 2020-2023  润新知