| package com.stylefeng.guns.config.web; | 
|   | 
| import com.stylefeng.guns.config.properties.GunsProperties; | 
| import com.stylefeng.guns.core.intercept.GunsUserFilter; | 
| import com.stylefeng.guns.core.shiro.ShiroDbRealm; | 
| import org.apache.shiro.cache.CacheManager; | 
| import org.apache.shiro.cache.ehcache.EhCacheManager; | 
| import org.apache.shiro.codec.Base64; | 
| import org.apache.shiro.session.mgt.SessionManager; | 
| import org.apache.shiro.spring.LifecycleBeanPostProcessor; | 
| import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor; | 
| import org.apache.shiro.spring.web.ShiroFilterFactoryBean; | 
| import org.apache.shiro.web.mgt.CookieRememberMeManager; | 
| import org.apache.shiro.web.mgt.DefaultWebSecurityManager; | 
| import org.apache.shiro.web.servlet.Cookie; | 
| import org.apache.shiro.web.servlet.ShiroHttpSession; | 
| import org.apache.shiro.web.servlet.SimpleCookie; | 
| import org.apache.shiro.web.session.mgt.DefaultWebSessionManager; | 
| import org.apache.shiro.web.session.mgt.ServletContainerSessionManager; | 
| import org.springframework.beans.factory.config.MethodInvokingFactoryBean; | 
| import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; | 
| import org.springframework.cache.ehcache.EhCacheManagerFactoryBean; | 
| import org.springframework.context.annotation.Bean; | 
| import org.springframework.context.annotation.Configuration; | 
|   | 
| import javax.servlet.Filter; | 
| import java.util.HashMap; | 
| import java.util.LinkedHashMap; | 
| import java.util.Map; | 
|   | 
| /** | 
|  * shiro权限管理的配置 | 
|  * | 
|  * @author fengshuonan | 
|  * @date 2016年11月14日 下午3:03:44 | 
|  */ | 
| @Configuration | 
| public class ShiroConfig { | 
|   | 
|     /** | 
|      * 安全管理器 | 
|      */ | 
|     @Bean | 
|     public DefaultWebSecurityManager securityManager(CookieRememberMeManager rememberMeManager, CacheManager cacheShiroManager, SessionManager sessionManager) { | 
|         DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); | 
|         securityManager.setRealm(this.shiroDbRealm()); | 
|         securityManager.setCacheManager(cacheShiroManager); | 
|         securityManager.setRememberMeManager(rememberMeManager); | 
|         securityManager.setSessionManager(sessionManager); | 
|         return securityManager; | 
|     } | 
|   | 
|     /** | 
|      * spring session管理器(多机环境) | 
|      */ | 
|     @Bean | 
|     @ConditionalOnProperty(prefix = "guns", name = "spring-session-open", havingValue = "true") | 
|     public ServletContainerSessionManager servletContainerSessionManager() { | 
|         return new ServletContainerSessionManager(); | 
|     } | 
|   | 
|     /** | 
|      * session管理器(单机环境) | 
|      */ | 
|     @Bean | 
|     @ConditionalOnProperty(prefix = "guns", name = "spring-session-open", havingValue = "false") | 
|     public DefaultWebSessionManager defaultWebSessionManager(CacheManager cacheShiroManager, GunsProperties gunsProperties) { | 
|         DefaultWebSessionManager sessionManager = new DefaultWebSessionManager(); | 
|         sessionManager.setCacheManager(cacheShiroManager); | 
|         sessionManager.setSessionValidationInterval(gunsProperties.getSessionValidationInterval() * 1000); | 
|         sessionManager.setGlobalSessionTimeout(gunsProperties.getSessionInvalidateTime() * 1000); | 
|         sessionManager.setDeleteInvalidSessions(true); | 
|         sessionManager.setSessionValidationSchedulerEnabled(true); | 
|         Cookie cookie = new SimpleCookie(ShiroHttpSession.DEFAULT_SESSION_ID_NAME); | 
|         cookie.setName("shiroCookie"); | 
|         cookie.setHttpOnly(true); | 
|         sessionManager.setSessionIdCookie(cookie); | 
|         return sessionManager; | 
|     } | 
|   | 
|     /** | 
|      * 缓存管理器 使用Ehcache实现 | 
|      */ | 
|     @Bean | 
|     public CacheManager getCacheShiroManager(EhCacheManagerFactoryBean ehcache) { | 
|         EhCacheManager ehCacheManager = new EhCacheManager(); | 
|         ehCacheManager.setCacheManager(ehcache.getObject()); | 
|         return ehCacheManager; | 
|     } | 
|   | 
|     /** | 
|      * 项目自定义的Realm | 
|      */ | 
|     @Bean | 
|     public ShiroDbRealm shiroDbRealm() { | 
|         return new ShiroDbRealm(); | 
|     } | 
|   | 
|     /** | 
|      * rememberMe管理器, cipherKey生成见{@code Base64Test.java} | 
|      */ | 
|     @Bean | 
|     public CookieRememberMeManager rememberMeManager(SimpleCookie rememberMeCookie) { | 
|         CookieRememberMeManager manager = new CookieRememberMeManager(); | 
| //        manager.setCipherKey(Base64.decode("Z3VucwAAAAAAAAAAAAAAAA=="));//取消硬编码密钥,防止Shiro反序列化漏洞 | 
|         manager.setCookie(rememberMeCookie); | 
|         return manager; | 
|     } | 
|   | 
|     /** | 
|      * 记住密码Cookie | 
|      */ | 
|     @Bean | 
|     public SimpleCookie rememberMeCookie() { | 
| //        SimpleCookie simpleCookie = new SimpleCookie("rememberMe");//取消记住我的cookie关键字,避免被扫描 | 
|         SimpleCookie simpleCookie = new SimpleCookie(""); | 
|         simpleCookie.setHttpOnly(true); | 
|         simpleCookie.setMaxAge(7 * 24 * 60 * 60);//7天 | 
|         return simpleCookie; | 
|     } | 
|   | 
|     /** | 
|      * Shiro的过滤器链 | 
|      */ | 
|     @Bean | 
|     public ShiroFilterFactoryBean shiroFilter(DefaultWebSecurityManager securityManager) { | 
|         ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean(); | 
|         shiroFilter.setSecurityManager(securityManager); | 
|         /** | 
|          * 默认的登录访问url | 
|          */ | 
|         shiroFilter.setLoginUrl("/login"); | 
|         /** | 
|          * 登录成功后跳转的url | 
|          */ | 
|         shiroFilter.setSuccessUrl("/"); | 
|         /** | 
|          * 没有权限跳转的url | 
|          */ | 
|         shiroFilter.setUnauthorizedUrl("/global/error"); | 
|   | 
|         /** | 
|          * 覆盖默认的user拦截器(默认拦截器解决不了ajax请求 session超时的问题,若有更好的办法请及时反馈作者) | 
|          */ | 
|         HashMap<String, Filter> myFilters = new HashMap<>(); | 
|         myFilters.put("user", new GunsUserFilter()); | 
|         shiroFilter.setFilters(myFilters); | 
|   | 
|         /** | 
|          * 配置shiro拦截器链 | 
|          * | 
|          * anon  不需要认证 | 
|          * authc 需要认证 | 
|          * user  验证通过或RememberMe登录的都可以 | 
|          * | 
|          * 当应用开启了rememberMe时,用户下次访问时可以是一个user,但不会是authc,因为authc是需要重新认证的 | 
|          * | 
|          * 顺序从上到下,优先级依次降低 | 
|          * | 
|          * api开头的接口,走rest api鉴权,不走shiro鉴权 | 
|          * | 
|          */ | 
|         Map<String, String> hashMap = new LinkedHashMap<>(); | 
|         hashMap.put("/swagger-ui.html", "anon"); | 
|         hashMap.put("/swagger-resources/**", "anon"); | 
|         hashMap.put("/v2/**", "anon"); | 
|         hashMap.put("/webjars/**", "anon"); | 
|         hashMap.put("/swagger-resources/configuration/ui/**", "anon"); | 
|         hashMap.put("/swagger-resources/configuration/security/**", "anon"); | 
|   | 
| //        hashMap.put("/base/**", "anon"); | 
|         hashMap.put("/upload/**", "anon"); | 
|         hashMap.put("/api/**", "anon"); | 
|         hashMap.put("/auth/**", "anon"); | 
|         hashMap.put("/static/**", "anon"); | 
|         hashMap.put("/gunsApi/**", "anon"); | 
|         hashMap.put("/login", "anon"); | 
|         hashMap.put("/login.html", "anon"); | 
|         hashMap.put("/updatepwdpage", "anon"); | 
|         hashMap.put("/updatepwd", "anon"); | 
|         hashMap.put("/global/sessionError", "anon"); | 
|         hashMap.put("/kaptcha", "anon"); | 
|         hashMap.put("/base/user/login", "anon"); | 
|         hashMap.put("/base/oss/upload", "anon"); | 
|         hashMap.put("/**", "user"); | 
|         shiroFilter.setFilterChainDefinitionMap(hashMap); | 
|         return shiroFilter; | 
|     } | 
|   | 
|     /** | 
|      * 在方法中 注入 securityManager,进行代理控制 | 
|      */ | 
|     @Bean | 
|     public MethodInvokingFactoryBean methodInvokingFactoryBean(DefaultWebSecurityManager securityManager) { | 
|         MethodInvokingFactoryBean bean = new MethodInvokingFactoryBean(); | 
|         bean.setStaticMethod("org.apache.shiro.SecurityUtils.setSecurityManager"); | 
|         bean.setArguments(new Object[]{securityManager}); | 
|         return bean; | 
|     } | 
|   | 
|     /** | 
|      * Shiro生命周期处理器: | 
|      * 用于在实现了Initializable接口的Shiro bean初始化时调用Initializable接口回调(例如:UserRealm) | 
|      * 在实现了Destroyable接口的Shiro bean销毁时调用 Destroyable接口回调(例如:DefaultSecurityManager) | 
|      */ | 
|     @Bean | 
|     public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() { | 
|         return new LifecycleBeanPostProcessor(); | 
|     } | 
|   | 
|     /** | 
|      * 启用shrio授权注解拦截方式,AOP式方法级权限检查 | 
|      */ | 
|     @Bean | 
|     public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager) { | 
|         AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = | 
|                 new AuthorizationAttributeSourceAdvisor(); | 
|         authorizationAttributeSourceAdvisor.setSecurityManager(securityManager); | 
|         return authorizationAttributeSourceAdvisor; | 
|     } | 
|   | 
| } |