记一下Shiro重构之ShiroConfig配置文件

ShiroConfig

所有的shiro配置都在这里面配就行了,你要是喜欢xml啥的就自己对应改下

package com.ccb.web.configs;

//shiro
import com.ccb.web.shiro.*;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.codec.Base64;
import org.apache.shiro.session.SessionListener;
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.web.ShiroFilterFactoryBean;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
//spring
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.config.MethodInvokingFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;
//java
import javax.servlet.Filter;
import java.io.Serializable;
import java.util.*;

/**
 * Shiro配置
 * 

* 大部分参数都是在这里直接修改 * * @author zhuyongsheng * @date 2019/8/13 */ @Configuration public class ShiroConfig { /** * ShiroFilterFactoryBean 处理拦截资源文件问题。 * 注意:初始化ShiroFilterFactoryBean的时候需要注入:SecurityManager * Web应用中,Shiro可控制的Web请求必须经过Shiro主过滤器的拦截 * * @return org.apache.shiro.spring.web.ShiroFilterFactoryBean * @author zhuyongsheng * @date 2019/8/15 */ @Bean(name = "shirFilter") public ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier("securityManager") SecurityManager securityManager) { //定义返回对象 ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); //必须设置 SecurityManager,Shiro的核心安全接口 shiroFilterFactoryBean.setSecurityManager(securityManager); //这里的/login是后台的接口名,非页面,如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面 shiroFilterFactoryBean.setLoginUrl("/sessionInvalid"); //这里的/index是后台的接口名,非页面,登录成功后要跳转的链接 shiroFilterFactoryBean.setSuccessUrl("/"); //未授权界面,该配置无效,并不会进行页面跳转 shiroFilterFactoryBean.setUnauthorizedUrl("/sessionInvalid"); //限制同一帐号同时在线的个数 LinkedHashMap<String, Filter> filtersMap = new LinkedHashMap<>(); filtersMap.put("kickout", kickoutSessionControlFilter()); shiroFilterFactoryBean.setFilters(filtersMap); // 配置访问权限 必须是LinkedHashMap,因为它必须保证有序 // 过滤链定义,从上向下顺序执行,一般将 /**放在最为下边 一定要注意顺序,否则就不好使了 LinkedHashMap<String, String> filterChainDefinitionMap = new LinkedHashMap<>(); //logout是shiro提供的过滤器 filterChainDefinitionMap.put("/logout", "logout"); //配置不登录可以访问的资源,anon 表示资源都可以匿名访问 filterChainDefinitionMap.put("/swagger-ui.html", "anon"); filterChainDefinitionMap.put("/webjars/**", "anon"); filterChainDefinitionMap.put("/swagger-resources/**", "anon"); filterChainDefinitionMap.put("/v2/**", "anon"); filterChainDefinitionMap.put("/u/**", "anon"); filterChainDefinitionMap.put("/swagger/**", "anon"); filterChainDefinitionMap.put("/doc.html", "anon"); filterChainDefinitionMap.put("/simpleBillRepertory/getShareStockUrl", "anon"); filterChainDefinitionMap.put("/alicheck", "anon"); filterChainDefinitionMap.put("/api-docs/**", "anon"); //此时访问/userInfo/del需要del权限,在自定义Realm中为用户授权。 //filterChainDefinitionMap.put("/userInfo/del", "perms[\"userInfo:del\"]"); //其他资源都需要认证 authc 表示需要认证才能进行访问 filterChainDefinitionMap.put("/**", "kickout,authc"); shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); return shiroFilterFactoryBean; } /** * 身份认证realm * * @return com.ccb.web.shiro.ShiroRealm * @author zhuyongsheng * @date 2019/8/15 */ @Bean public ShiroRealm shiroRealm() { ShiroRealm shiroRealm = new ShiroRealm(); shiroRealm.setCachingEnabled(true); //启用身份验证缓存,即缓存AuthenticationInfo信息,默认false shiroRealm.setAuthenticationCachingEnabled(true); //缓存AuthenticationInfo信息的缓存名称 在ehcache-shiro.xml中有对应缓存的配置 shiroRealm.setAuthenticationCacheName("authenticationCache"); //启用授权缓存,即缓存AuthorizationInfo信息,默认false shiroRealm.setAuthorizationCachingEnabled(true); //缓存AuthorizationInfo信息的缓存名称 在ehcache-shiro.xml中有对应缓存的配置 shiroRealm.setAuthorizationCacheName("authorizationCache"); return shiroRealm; } /** * cookie管理对象;记住我功能,rememberMe管理器 * * @return org.apache.shiro.web.mgt.CookieRememberMeManager * @author zhuyongsheng * @date 2019/8/15 */ @Bean public CookieRememberMeManager cookieRememberMeManager() { CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager(); cookieRememberMeManager.setCookie(simpleCookie()); //rememberMe cookie加密的密钥 建议每个项目都不一样 默认AES算法 密钥长度(128 256 512 位) cookieRememberMeManager.setCipherKey(Base64.decode("4AvVhmFLUs0KTA3Kprsdag==")); return cookieRememberMeManager; } /** * shiro缓存管理器 * * @return org.apache.shiro.cache.ehcache.EhCacheManager * @author zhuyongsheng * @date 2019/8/15 */ @Bean public EhCacheManager ehCacheManager() { EhCacheManager cacheManager = new EhCacheManager(); cacheManager.setCacheManagerConfigFile("classpath:ehcache-shiro.xml"); return cacheManager; } /** * redisTemplate 配置 * * @param redisConnectionFactory * @return */ @Bean("csRedisTemplate") public RedisTemplate<String, Serializable> csRedisTemplate(LettuceConnectionFactory redisConnectionFactory) { ObjectMapper om = new ObjectMapper(); // 4.设置可见度 om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); // 5.启动默认的类型 om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); //解决实体缺少 set get 方法 om.configure(MapperFeature.USE_GETTERS_AS_SETTERS, false); //截取实体缺少的属性 om.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); RedisTemplate<String, Serializable> template = new RedisTemplate<>(); template.setKeySerializer(new StringRedisSerializer()); template.setValueSerializer(new GenericJackson2JsonRedisSerializer(om)); template.setHashKeySerializer(new StringRedisSerializer()); template.setDefaultSerializer(new GenericJackson2JsonRedisSerializer(om)); template.setConnectionFactory(redisConnectionFactory); return template; } @Bean("csRedisUtil") public CsRedisUtil csRedisUtil(@Qualifier("csRedisTemplate") RedisTemplate<String, Serializable> redisTemplate) { CsRedisUtil redisUtil = new CsRedisUtil(); redisUtil.setRedisTemplate(redisTemplate); return redisUtil; } /** * 配置会话管理器,设定会话超时及保存 * * @return org.apache.shiro.session.mgt.SessionManager * @author zhuyongsheng * @date 2019/8/15 */ @Bean("shiroSessionManager") public ShiroSessionManager shiroSessionManager() { ShiroSessionManager sessionManager = new ShiroSessionManager(); Collection<SessionListener> listeners = new ArrayList<>(); //配置监听 listeners.add(shiroSessionListener()); sessionManager.setSessionListeners(listeners); sessionManager.setSessionIdCookie(sessionIdCookie()); sessionManager.setSessionDAO(redisSessionDAO()); sessionManager.setCacheManager(ehCacheManager()); //全局会话超时时间(单位毫秒) sessionManager.setGlobalSessionTimeout(60 * 1000 * 60); //是否开启删除无效的session对象 默认为true sessionManager.setDeleteInvalidSessions(true); //是否开启定时调度器进行检测过期session 默认为true sessionManager.setSessionValidationSchedulerEnabled(true); //设置session失效的扫描时间, 清理用户直接关闭浏览器造成的孤立会话 //设置该属性 就不需要设置 ExecutorServiceSessionValidationScheduler 底层也是默认自动调用ExecutorServiceSessionValidationScheduler sessionManager.setSessionValidationInterval(60 * 1000 * 10); sessionManager.setSessionFactory(shiroSessionFactory()); //取消url 后面的 JSESSIONID sessionManager.setSessionIdUrlRewritingEnabled(false); return sessionManager; } /** * 配置核心安全事务管理器 * * @return org.apache.shiro.mgt.SecurityManager * @author zhuyongsheng * @date 2019/8/15 */ @Bean(name = "securityManager") public SecurityManager securityManager() { DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); //设置自定义realm. securityManager.setRealm(shiroRealm()); //配置记住我 securityManager.setRememberMeManager(cookieRememberMeManager()); //配置缓存管理器 securityManager.setCacheManager(ehCacheManager()); //配置session管理器 securityManager.setSessionManager(shiroSessionManager()); return securityManager; } /** * FormAuthenticationFilter 过滤器 过滤记住我 * * @return org.apache.shiro.web.filter.authc.FormAuthenticationFilter * @author zhuyongsheng * @date 2019/8/15 */ @Bean public FormAuthenticationFilter formAuthenticationFilter() { FormAuthenticationFilter formAuthenticationFilter = new FormAuthenticationFilter(); //对应前端的checkbox的name = rememberMe formAuthenticationFilter.setRememberMeParam("rememberMe"); return formAuthenticationFilter; } /** * 并发登录控制 * * @return com.ccb.web.shiro.KickoutSessionControlFilter * @author zhuyongsheng * @date 2019/8/15 */ @Bean public KickoutSessionControlFilter kickoutSessionControlFilter() { KickoutSessionControlFilter kickoutSessionControlFilter = new KickoutSessionControlFilter(); //使用cacheManager获取相应的cache来缓存用户登录的会话;用于保存用户—会话之间的关系的; kickoutSessionControlFilter.setCacheManager(ehCacheManager()); //是否踢出后来登录的,默认是false;即后者登录的用户踢出前者登录的用户; kickoutSessionControlFilter.setKickoutAfter(false); //同一个用户最大的会话数,默认1;比如2的意思是同一个用户允许最多同时两个人登录; kickoutSessionControlFilter.setMaxSession(1); //被踢出后重定向到的地址; kickoutSessionControlFilter.setKickoutUrl("/login?kickout=1"); return kickoutSessionControlFilter; } /** * 配置Shiro生命周期处理器 * * @return org.apache.shiro.spring.LifecycleBeanPostProcessor * @author zhuyongsheng * @date 2019/8/15 */ @Bean(name = "lifecycleBeanPostProcessor") public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() { return new LifecycleBeanPostProcessor(); } /** * shiro缓存管理器 * * @return com.ccb.web.shiro.RedisCacheManager * @author zhuyongsheng * @date 2019/8/15 */ @Bean public RedisCacheManager redisCacheManager() { RedisCacheManager redisCacheManager = new RedisCacheManager(); //redis中针对不同用户缓存 redisCacheManager.setPrincipalIdFieldName("username"); //用户权限信息缓存时间 redisCacheManager.setExpire(60 * 1000 * 60); return redisCacheManager; } /** * redis 替代默认缓存 * * @return com.ccb.web.shiro.RedisSessionDAO * @author zhuyongsheng * @date 2019/8/15 */ @Bean public RedisSessionDAO redisSessionDAO() { RedisSessionDAO redisSessionDAO = new RedisSessionDAO(); redisSessionDAO.setExpire(60 * 60); return redisSessionDAO; } /** * SessionDAO的作用是为Session提供CRUD并进行持久化的一个shiro组件 * * @return org.apache.shiro.session.mgt.eis.SessionDAO * @author zhuyongsheng * @date 2019/8/15 */ @Bean public SessionDAO sessionDAO() { RedisSessionDAO redisSessionDAO = redisSessionDAO(); //使用ehCacheManager redisSessionDAO.setCacheManager(ehCacheManager()); //设置session缓存的名字 默认为 shiro-activeSessionCache redisSessionDAO.setActiveSessionsCacheName("shiro-activeSessionCache"); //sessionId生成器 redisSessionDAO.setSessionIdGenerator(sessionIdGenerator()); return redisSessionDAO; } /** * 配置保存sessionId的cookie * 注意:这里的cookie 不是上面的记住我 cookie 记住我需要一个cookie session管理 也需要自己的cookie * * @return org.apache.shiro.web.servlet.SimpleCookie * @author zhuyongsheng * @date 2019/8/15 */ @Bean("sessionIdCookie") public SimpleCookie sessionIdCookie() { //这个参数是cookie的名称 SimpleCookie simpleCookie = new SimpleCookie("sid"); simpleCookie.setHttpOnly(true); simpleCookie.setPath("/"); //maxAge=-1表示浏览器关闭时失效此Cookie simpleCookie.setMaxAge(-1); return simpleCookie; } /** * 配置会话ID生成器 * * @return org.apache.shiro.session.mgt.eis.SessionIdGenerator * @author zhuyongsheng * @date 2019/8/15 */ @Bean public SessionIdGenerator sessionIdGenerator() { return new JavaUuidSessionIdGenerator(); } /** * session工厂 * * @return com.ccb.web.shiro.ShiroSessionFactory * @author zhuyongsheng * @date 2019/8/15 */ @Bean("sessionFactory") public ShiroSessionFactory shiroSessionFactory() { ShiroSessionFactory sessionFactory = new ShiroSessionFactory(); return sessionFactory; } /** * 配置session监听 * * @return com.ccb.web.shiro.ShiroSessionListener * @author zhuyongsheng * @date 2019/8/15 */ @Bean("sessionListener") public ShiroSessionListener shiroSessionListener() { ShiroSessionListener sessionListener = new ShiroSessionListener(); return sessionListener; } /** * cookie对象;会话Cookie模板 ,默认为: JSESSIONID 问题: 与SERVLET容器名冲突,重新定义为sid或rememberMe * * @return org.apache.shiro.web.servlet.SimpleCookie * @author zhuyongsheng * @date 2019/8/15 */ @Bean public SimpleCookie simpleCookie() { //这个参数是cookie的名称,对应前端的checkbox的name = rememberMe SimpleCookie simpleCookie = new SimpleCookie("rememberMe"); /* * 设为true后,只能通过http访问,javascript无法访问 * 防止xss读取cookie */ simpleCookie.setHttpOnly(true); simpleCookie.setPath("/"); // simpleCookie.setMaxAge(2592000); return simpleCookie; } /** * 解决: 无权限页面不跳转 * * @return org.springframework.web.servlet.handler.SimpleMappingExceptionResolver * @author zhuyongsheng * @date 2019/8/15 * @apiNote shiroFilterFactoryBean.setUnauthorizedUrl(" / unauthorized ") 无效 * shiro的源代码ShiroFilterFactoryBean.Java定义的filter必须满足filter instanceof AuthorizationFilter, * 只有perms,roles,ssl,rest,port才是属于AuthorizationFilter,而anon,authcBasic,auchc,user是AuthenticationFilter, * 所以unauthorizedUrl设置后页面不跳转 Shiro注解模式下,登录失败与没有权限都是通过抛出异常。 * 并且默认并没有去处理或者捕获这些异常。在SpringMVC下需要配置捕获相应异常来通知用户信息 */ @Bean public SimpleMappingExceptionResolver simpleMappingExceptionResolver() { SimpleMappingExceptionResolver simpleMappingExceptionResolver = new SimpleMappingExceptionResolver(); Properties properties = new Properties(); //这里的 /unauthorized 是页面,不是访问的路径 properties.setProperty("org.apache.shiro.authz.UnauthorizedException", "/unauthorized"); properties.setProperty("org.apache.shiro.authz.UnauthenticatedException", "/unauthorized"); simpleMappingExceptionResolver.setExceptionMappings(properties); return simpleMappingExceptionResolver; } /** * 让某个实例的某个方法的返回值注入为Bean的实例 * Spring静态注入 * * @return */ @Bean public MethodInvokingFactoryBean getMethodInvokingFactoryBean() { MethodInvokingFactoryBean factoryBean = new MethodInvokingFactoryBean(); factoryBean.setStaticMethod("org.apache.shiro.SecurityUtils.setSecurityManager"); factoryBean.setArguments(new Object[]{securityManager()}); return factoryBean; } }

你可能感兴趣的:(Shiro)