package com.bootdo.system.config; import at.pollux.thymeleaf.shiro.dialect.ShiroDialect; import com.bootdo.common.config.Constant; import com.bootdo.common.redis.shiro.RedisCacheManager; import com.bootdo.common.redis.shiro.RedisManager; import com.bootdo.common.redis.shiro.RedisSessionDAO; import com.bootdo.system.shiro.SystemShiroFilterFactoryBean; import com.bootdo.system.shiro.SystemLogoutFilter; import com.bootdo.system.shiro.UserRealm; import net.sf.ehcache.CacheManager; import org.apache.shiro.cache.ehcache.EhCacheManager; import org.apache.shiro.mgt.SecurityManager; import org.apache.shiro.session.SessionListener; import org.apache.shiro.session.mgt.ExecutorServiceSessionValidationScheduler; import org.apache.shiro.session.mgt.eis.MemorySessionDAO; import org.apache.shiro.session.mgt.eis.SessionDAO; import org.apache.shiro.spring.LifecycleBeanPostProcessor; import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor; import org.apache.shiro.web.mgt.DefaultWebSecurityManager; import org.apache.shiro.web.session.mgt.DefaultWebSessionManager; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import javax.servlet.Filter; import java.util.ArrayList; import java.util.Collection; import java.util.LinkedHashMap; import java.util.List; /** * @author bootdo 1992lcg@163.com */ @Configuration public class ShiroConfig { @Value("${spring.cache.type}") private String cacheType ; @Value("${server.session-timeout}") private int tomcatTimeout; @Bean public static LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() { return new LifecycleBeanPostProcessor(); } /** * ShiroDialect,为了在thymeleaf里使用shiro的标签的bean * * @return */ @Bean public ShiroDialect shiroDialect() { return new ShiroDialect(); } /** * Shiro的Web过滤器 * * @param securityManager 项目 * @return */ @Bean public SystemShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) { SystemShiroFilterFactoryBean factory = new SystemShiroFilterFactoryBean(); // 拦截器 LinkedHashMap filtersMap = new LinkedHashMap<>(); //配置自定义登出 覆盖 logout 之前默认的LogoutFilter filtersMap.put("logout", shiroLogoutFilter()); factory.setFilters(filtersMap); factory.setSecurityManager(securityManager); factory.setLoginUrl("/login"); factory.setSuccessUrl("/index"); factory.setUnauthorizedUrl("/403"); // url过滤规则 LinkedHashMap filterChainDefinitionMap = new LinkedHashMap<>(); filterChainDefinitionMap.put("/getLoginUrl", "anon"); filterChainDefinitionMap.put("/login", "anon"); filterChainDefinitionMap.put("/ssoLogin", "anon"); filterChainDefinitionMap.put("/sys/online/**", "anon"); filterChainDefinitionMap.put("/code", "anon"); filterChainDefinitionMap.put("/sso/**", "anon"); filterChainDefinitionMap.put("/getVerify", "anon"); filterChainDefinitionMap.put("/css/**", "anon"); filterChainDefinitionMap.put("/js/**", "anon"); filterChainDefinitionMap.put("/fonts/**", "anon"); filterChainDefinitionMap.put("/img/**", "anon"); filterChainDefinitionMap.put("/docs/**", "anon"); filterChainDefinitionMap.put("/druid/**", "anon"); filterChainDefinitionMap.put("/upload/**", "anon"); filterChainDefinitionMap.put("/files/**", "anon"); //filterChainDefinitionMap.put("/logout", "logout"); filterChainDefinitionMap.put("/", "anon"); filterChainDefinitionMap.put("/blog", "anon"); filterChainDefinitionMap.put("/blog/open/**", "anon"); filterChainDefinitionMap.put("/sms/**", "anon"); // 门户接口匿名访问 filterChainDefinitionMap.put("/portal/**", "anon"); filterChainDefinitionMap.put("/api/**", "anon"); filterChainDefinitionMap.put("/**", "authc"); factory.setFilterChainDefinitionMap(filterChainDefinitionMap); // session过滤白名单 List whiteList = new ArrayList<>(); whiteList.add("/code"); factory.setWHITELIST(whiteList); return factory; } @Bean public SecurityManager securityManager() { DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); //设置realm. securityManager.setRealm(userRealm()); // 自定义缓存实现 使用redis if (Constant.CACHE_TYPE_REDIS.equals(cacheType)) { securityManager.setCacheManager(rediscacheManager()); } else { securityManager.setCacheManager(ehCacheManager()); } securityManager.setSessionManager(sessionManager()); return securityManager; } /** * 配置LogoutFilter * * @return */ public SystemLogoutFilter shiroLogoutFilter() { SystemLogoutFilter shiroLogoutFilter = new SystemLogoutFilter(); //配置登出后重定向的地址,等出后配置跳转到登录接口 // shiroLogoutFilter.setRedirectUrl("/login"); return shiroLogoutFilter; } @Bean UserRealm userRealm() { UserRealm userRealm = new UserRealm(); return userRealm; } /** * 开启shiro aop注解支持. * 使用代理方式;所以需要开启代码支持; * * @param securityManager * @return */ @Bean public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) { AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor(); authorizationAttributeSourceAdvisor.setSecurityManager(securityManager); return authorizationAttributeSourceAdvisor; } /** * 配置shiro redisManager * * @return */ @Bean public RedisManager redisManager() { RedisManager redisManager = new RedisManager(); redisManager.setExpire(1800);// 配置缓存过期时间 return redisManager; } /** * cacheManager 缓存 redis实现 * 使用的是shiro-redis开源插件 * * @return */ public RedisCacheManager rediscacheManager() { RedisCacheManager redisCacheManager = new RedisCacheManager(); redisCacheManager.setRedisManager(redisManager()); return redisCacheManager; } /** * RedisSessionDAO shiro sessionDao层的实现 通过redis * 使用的是shiro-redis开源插件 */ @Bean public RedisSessionDAO redisSessionDAO() { RedisSessionDAO redisSessionDAO = new RedisSessionDAO(); redisSessionDAO.setRedisManager(redisManager()); return redisSessionDAO; } @Bean public SessionDAO sessionDAO() { if (Constant.CACHE_TYPE_REDIS.equals(cacheType)) { return redisSessionDAO(); } else { return new MemorySessionDAO(); } } /** * shiro session的管理 */ @Bean public DefaultWebSessionManager sessionManager() { DefaultWebSessionManager sessionManager = new DefaultWebSessionManager(); // 设置回话过期时间 sessionManager.setGlobalSessionTimeout(tomcatTimeout * 1000L); // 判定使用内存还是redis sessionManager.setSessionDAO(sessionDAO()); // 取消登录成功后url 后面的 JSESSIONID sessionManager.setSessionIdUrlRewritingEnabled(false); // 删除过期的session sessionManager.setDeleteInvalidSessions(true); // 定时检测session过期,90s检测一次 sessionManager.setSessionValidationSchedulerEnabled(true); ExecutorServiceSessionValidationScheduler validationScheduler = new ExecutorServiceSessionValidationScheduler( sessionManager); validationScheduler.setInterval(90000L); sessionManager.setSessionValidationScheduler(validationScheduler); Collection listeners = new ArrayList(); listeners.add(new BDSessionListener()); sessionManager.setSessionListeners(listeners); return sessionManager; } @Bean public EhCacheManager ehCacheManager() { EhCacheManager em = new EhCacheManager(); em.setCacheManager(cacheManager()); return em; } @Bean("cacheManager2") CacheManager cacheManager(){ return CacheManager.create(); } }