package com.project.shiro.config; import com.project.shiro.util.AuthenticationFilter; import com.project.shiro.util.AuthenticationRealm; import com.project.shiro.util.AuthorizationFilter; import com.project.shiro.util.redis.ShiroRedisCacheManager; import com.project.shiro.util.redis.ShiroRedisSessionDAO; 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.DefaultWebSecurityManager; import org.apache.shiro.web.servlet.SimpleCookie; import org.apache.shiro.web.session.mgt.DefaultWebSessionManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; 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 javax.servlet.Filter; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; /** * Description: shiro配置类 * User: mxy * Date: 2019-04-16 */ @Configuration public class ShiroConfig { private static final transient Logger logger = LoggerFactory.getLogger(ShiroConfig.class); /** * 配置拦截器 * <p> * 定义拦截URL权限,优先级从上到下 * 1). anon : 匿名访问,无需登录 * 2). authc : 登录后才能访问 * 3). logout: 登出 * 4). frameperms : 自定义的过滤器 * <p> * URL 匹配风格 * 1). ?:匹配一个字符,如 /admin? 将匹配 /admin1,但不匹配 /admin 或 /admin/; * 2). *:匹配零个或多个字符串,如 /admin* 将匹配 /admin 或/admin123,但不匹配 /admin/1; * 3). **:匹配路径中的零个或多个路径,如 /admin/** 将匹配 /admin/a 或 /admin/a/b * <p> * 配置身份验证成功,失败的跳转路径 */ @Bean public ShiroFilterFactoryBean shiroFilter(DefaultWebSecurityManager securityManager) { logger.info("进入Shiro拦截工厂"); ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); // 设置securityManager shiroFilterFactoryBean.setSecurityManager(securityManager); // 自定义的过滤器 Map<String, Filter> filterMap = new HashMap<>(); // map里面key值要为过滤器的名称,value为过滤器对象 filterMap.put("authc", authenticationFilter()); filterMap.put("frameperms", authorizationFilter()); // 将自定义的过滤器加入到过滤器集合中 shiroFilterFactoryBean.setFilters(filterMap); // 设置拦截器集合 Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>(); filterChainDefinitionMap.put("/admin/", "anon"); // 后台资源-匿名访问 filterChainDefinitionMap.put("/admin/res/**", "anon"); // 静态资源-匿名访问 filterChainDefinitionMap.put("/admin/anon/**", "anon"); // 后台可匿名访问资源-匿名访问 filterChainDefinitionMap.put("/admin/login", "authc"); // 登录页面-身份认证 filterChainDefinitionMap.put("/admin/logout", "logout"); // 用户退出,只需配置logout即可实现该功能 filterChainDefinitionMap.put("/admin/common/**", "anon"); // 其他路径均需要身份认证,一般位于最下面,优先级最低 filterChainDefinitionMap.put("/admin/**", "authc,frameperms"); // 其他路径均需要身份认证,一般位于最下面,优先级最低 // 设置拦截器 shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); shiroFilterFactoryBean.setLoginUrl("/admin/login"); // 登录的路径 // shiroFilterFactoryBean.setUnauthorizedUrl("/admin/common/unauthorized.jhtml"); // 验证失败后跳转的路径 logger.info("Shiro拦截工厂配置完成"); return shiroFilterFactoryBean; } /** * 配置Shiro生命周期处理器 */ @Bean public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() { return new LifecycleBeanPostProcessor(); } /** * 自动创建代理类,若不添加,Shiro的注解可能不会生效。 */ @Bean @DependsOn({"lifecycleBeanPostProcessor"}) public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator() { DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator(); advisorAutoProxyCreator.setProxyTargetClass(true); return advisorAutoProxyCreator; } /** * 开启Shiro的注解 */ @Bean public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor() { AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor(); authorizationAttributeSourceAdvisor.setSecurityManager(securityManager()); return authorizationAttributeSourceAdvisor; } /** * 配置加密匹配,使用MD5的方式,进行1024次加密 */ // @Bean // public HashedCredentialsMatcher hashedCredentialsMatcher() { // HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher(); // hashedCredentialsMatcher.setHashAlgorithmName("MD5"); // hashedCredentialsMatcher.setHashIterations(1024); // return hashedCredentialsMatcher; // } /** * SecurityManager 安全管理器;Shiro的核心 */ @Bean public DefaultWebSecurityManager securityManager() { DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); // 自定义的Realm securityManager.setRealm(authenticationShiroRealm()); // 缓存管理 securityManager.setCacheManager(shiroRedisCacheManager()); // 会话管理 securityManager.setSessionManager(sessionManager()); return securityManager; } /** * 自定义Realm,可以多个 */ @Bean public AuthenticationRealm authenticationShiroRealm() { AuthenticationRealm authenticationRealm = new AuthenticationRealm(); //authenticationRealm.setCredentialsMatcher(hashedCredentialsMatcher()); return authenticationRealm; } /** * redis缓存管理 */ @Bean public ShiroRedisCacheManager shiroRedisCacheManager() { return new ShiroRedisCacheManager(); } /** * 设置session会话管理者 */ @Bean public SessionManager sessionManager() { DefaultWebSessionManager defaultWebSessionManager = new DefaultWebSessionManager(); defaultWebSessionManager.setSessionIdCookie(simpleCookie()); defaultWebSessionManager.setSessionDAO(shiroRedisSessionDAO()); return defaultWebSessionManager; } /** * session管理 */ @Bean public ShiroRedisSessionDAO shiroRedisSessionDAO() { return new ShiroRedisSessionDAO(); } /** * 这里需要设置一个cookie的名称 原因就是会跟原来的session的id值重复的 */ @Bean public SimpleCookie simpleCookie() { return new SimpleCookie("SHAREJSESSIONID"); } @Bean public AuthenticationFilter authenticationFilter() { return new AuthenticationFilter(); } @Bean public AuthorizationFilter authorizationFilter() { return new AuthorizationFilter(); } }