package com.qxgmat.util.shiro; import com.nuliji.tools.shiro.*; import com.nuliji.tools.shiro.cache.RedisManager; import com.nuliji.tools.shiro.cache.CustomCacheManager; import com.nuliji.tools.shiro.cache.RedisCacheProvider; import com.nuliji.tools.shiro.inter.HeaderTokenManager; import com.nuliji.tools.shiro.session.CustomSessionDao; import com.nuliji.tools.shiro.session.RedisSessionRepository; import com.nuliji.tools.shiro.session.SessionRepository; import com.qxgmat.util.shiro.impl.UserTokenManager; import org.apache.shiro.authc.credential.HashedCredentialsMatcher; import org.apache.shiro.authc.pam.AtLeastOneSuccessfulStrategy; import org.apache.shiro.cache.CacheManager; import org.apache.shiro.codec.Base64; import org.apache.shiro.realm.Realm; import org.apache.shiro.session.Session; import org.apache.shiro.session.SessionListener; import org.apache.shiro.session.mgt.ExecutorServiceSessionValidationScheduler; import org.apache.shiro.session.mgt.SessionManager; import org.apache.shiro.session.mgt.eis.JavaUuidSessionIdGenerator; import org.apache.shiro.session.mgt.eis.SessionDAO; import org.apache.shiro.session.mgt.eis.SessionIdGenerator; 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.spring.web.config.DefaultShiroFilterChainDefinition; import org.apache.shiro.spring.web.config.ShiroFilterChainDefinition; 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.SimpleCookie; import org.apache.shiro.web.session.mgt.DefaultWebSessionManager; import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.DependsOn; import org.springframework.data.redis.connection.RedisConnectionFactory; import javax.servlet.Filter; import java.io.Serializable; import java.util.ArrayList; import java.util.Collection; import java.util.Map; @Configuration public class ShiroConfig { @Bean public ShiroFilterChainDefinition shiroFilterChainDefinition() { DefaultShiroFilterChainDefinition chain = new DefaultShiroFilterChainDefinition(); chain.addPathDefinition("/admin/auth/**", "anon"); chain.addPathDefinition("/admin/**", "role[manager]"); chain.addPathDefinition("/api/auth/**", "anon"); chain.addPathDefinition("/api/my/**", "token,role[user]"); chain.addPathDefinition("/**", "anon"); return chain; } @Bean(name = "shiroFilter") public ShiroFilterFactoryBean getShiroFilterFactoryBean(DefaultWebSecurityManager securityManager) { ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); // 必须设置 SecurityManager shiroFilterFactoryBean.setSecurityManager(securityManager); Map filters = shiroFilterFactoryBean.getFilters(); DevelopFilter developFilter = new DevelopFilter(); RoleFilter roleFilter = new RoleFilter(); TokenFilter tokenFilter = new TokenFilter(headerTokenManager()); filters.put("role", roleFilter); filters.put("develop", developFilter); filters.put("token", tokenFilter); shiroFilterFactoryBean.setFilters(filters); shiroFilterFactoryBean.setFilterChainDefinitionMap(shiroFilterChainDefinition().getFilterChainMap()); return shiroFilterFactoryBean; } @Bean public RedisManager redisManager(RedisConnectionFactory factory){ RedisManager redisManager = new RedisManager(); redisManager.setFactory(factory); redisManager.setExpire(86400000); return redisManager; } @Bean public RedisCacheProvider redisCacheProvider(RedisManager redisManager){ RedisCacheProvider redisCacheProvider = new RedisCacheProvider(); redisCacheProvider.setRedisManager(redisManager); return redisCacheProvider; } @Bean public SessionRepository redisSessionRepository(RedisManager redisManager){ RedisSessionRepository redisSessionRepository = new RedisSessionRepository(); redisSessionRepository.setRedisManager(redisManager); return redisSessionRepository; } @Bean public CacheManager customCacheManager(RedisCacheProvider redisCacheProvider){ CustomCacheManager customCacheManager = new CustomCacheManager(); customCacheManager.setCacheProvider(redisCacheProvider); return customCacheManager; } /** * 加密方式 * * @return */ @Bean public HashedCredentialsMatcher hashedCredentialsMatcher() { HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher(); hashedCredentialsMatcher.setHashAlgorithmName("md5");// 散列算法:这里使用MD5算法; hashedCredentialsMatcher.setHashIterations(2);// 散列的次数,比如散列两次,相当于md5(md5("")); hashedCredentialsMatcher.setStoredCredentialsHexEncoded(false);// 表示是否存储散列后的密码为16进制,需要和生成密码时的一样,默认是base64; return hashedCredentialsMatcher; } @Bean public HeaderTokenManager headerTokenManager() { UserTokenManager userTokenManager = new UserTokenManager(); return userTokenManager; } @Bean public UserRealm userRealm() { UserRealm userRealm = new UserRealm(); // userRealm.setCredentialsMatcher(new SimpleCredentialsMatcher()); userRealm.setCachingEnabled(true); return userRealm; } @Bean public TokenRealm tokenRealm() { TokenRealm tokenRealm = new TokenRealm(); // userRealm.setCredentialsMatcher(new SimpleCredentialsMatcher()); tokenRealm.setCachingEnabled(true); return tokenRealm; } @Bean public ManagerRealm managerRealm() { ManagerRealm managerRealm = new ManagerRealm(); // managerRealm.setCredentialsMatcher(new SimpleCredentialsMatcher()); managerRealm.setCachingEnabled(true); return managerRealm; } @Bean public OauthRealm oauthRealm(){ OauthRealm oauthRealm = new OauthRealm(); oauthRealm.setCachingEnabled(false); return oauthRealm; } @Bean public DevelopRealm developRealm(){ DevelopRealm developRealm = new DevelopRealm(); developRealm.setCachingEnabled(true); return developRealm; } @Bean public Collection realms() { Collection realms = new ArrayList<>(); realms.add(userRealm()); realms.add(tokenRealm()); realms.add(oauthRealm()); realms.add(managerRealm()); realms.add(developRealm()); return realms; } /** * 配置认证策略,只要有一个Realm认证成功即可,并且返回所有认证成功信息 * * @return */ @Bean AtLeastOneSuccessfulStrategy authenticationStrategy() { return new AtLeastOneSuccessfulStrategy(); } /** * 配置使用自定义认证器,可以实现多Realm认证,并且可以指定特定Realm处理特定类型的验证 * * @return */ @Bean RealmAuthenticator authenticator() { RealmAuthenticator authenticator = new RealmAuthenticator(); authenticator.setAuthenticationStrategy(authenticationStrategy()); return authenticator; } @Bean public Cookie rememberMeCookie() { // 这个参数是cookie的名称,对应前端的checkbox的name = rememberMe SimpleCookie simpleCookie = new SimpleCookie("rememberMe"); // simpleCookie.setMaxAge(259200); return simpleCookie; } /** * CookieRememberMeManager * * @return */ @Bean public CookieRememberMeManager rememberMeManager() { CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager(); cookieRememberMeManager.setCookie(rememberMeCookie()); cookieRememberMeManager.setCipherKey(Base64.decode("2AvVhdsgUs0FSA3SDFAdag==")); return cookieRememberMeManager; } // @Bean // public MyShiroSessionListener myShiroSessionListener() { // return new MyShiroSessionListener(); // } /** * 会话监听器 * * @return */ @Bean public Collection sessionListeners() { Collection listeners = new ArrayList<>(); // listeners.add(myShiroSessionListener()); return listeners; } /** * 会话ID生成器 * * @return */ @Bean public SessionIdGenerator sessionIdGenerator() { SessionIdGenerator idGenerator = new SessionIdGenerator() { @Override public Serializable generateId(Session session) { Serializable uuid = new JavaUuidSessionIdGenerator().generateId(session); System.out.println("sessionIdGenerator:" + uuid); return uuid; } }; return idGenerator; } /** * 会话DAO * * @return */ @Bean public CustomSessionDao sessionDao(SessionRepository sessionRepository) { CustomSessionDao sessionDao = new CustomSessionDao(); sessionDao.setSessionRepository(sessionRepository); sessionDao.setSessionIdGenerator(sessionIdGenerator()); return sessionDao; } /** * 处理session有效期 * * @return */ @Bean public ExecutorServiceSessionValidationScheduler sessionValidationScheduler() { ExecutorServiceSessionValidationScheduler sessionValidationScheduler = new ExecutorServiceSessionValidationScheduler(); sessionValidationScheduler.setInterval(1800000); return sessionValidationScheduler; } @Bean(name = "sessionManager") public SessionManager sessionManager(SessionDAO sessionDAO) { DefaultWebSessionManager sessionManager = new DefaultWebSessionManager(); Cookie sessionIdCookie = new SimpleCookie("JSESSIONID"); sessionIdCookie.setPath("/"); sessionManager.setSessionIdCookie(sessionIdCookie); sessionManager.setGlobalSessionTimeout(86400000); sessionManager.setDeleteInvalidSessions(true); sessionManager.setSessionIdUrlRewritingEnabled(false); sessionManager.setSessionValidationScheduler(sessionValidationScheduler()); sessionManager.setSessionValidationSchedulerEnabled(true); sessionManager.setSessionListeners(sessionListeners()); sessionManager.setSessionDAO(sessionDAO); return sessionManager; } /** * 会话管理器 * * @return */ @Bean(name = "securityManager") public DefaultWebSecurityManager securityManager(CacheManager cacheManager, SessionManager sessionManager) { DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); securityManager.setCacheManager(cacheManager); securityManager.setAuthenticator(authenticator()); securityManager.setRememberMeManager(rememberMeManager()); securityManager.setRealms(realms()); securityManager.setSessionManager(sessionManager); return securityManager; } /** * 开启shiro注解 ---- 注解权限 * * @param securityManager * @return */ @Bean public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(org.apache.shiro.mgt.SecurityManager securityManager) { AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor(); authorizationAttributeSourceAdvisor.setSecurityManager(securityManager); return authorizationAttributeSourceAdvisor; } /** * Shiro生命周期处理器 ---可以自定的来调用配置在 Spring IOC 容器中 shiro bean 的生命周期方法. * * @return */ @Bean public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() { return new LifecycleBeanPostProcessor(); } /** * 开启shiro注解 ----启用 IOC 容器中使用 shiro 的注解. 但必须在配置了 LifecycleBeanPostProcessor * 之后才可以使用 * * @return */ @Bean @DependsOn("lifecycleBeanPostProcessor") public DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() { DefaultAdvisorAutoProxyCreator daap = new DefaultAdvisorAutoProxyCreator(); daap.setProxyTargetClass(true); return daap; } }