ShiroConfiguration
package com.energy.common.config; import java.util.LinkedHashMap; import java.util.Map; import javax.servlet.Filter; import org.apache.shiro.authc.credential.HashedCredentialsMatcher; import org.apache.shiro.cache.ehcache.EhCacheManager; 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.SimpleCookie; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.DependsOn; import com.energy.common.util.MyFormAuthenticationFilter; import com.energy.common.util.MyShiroRealm; import at.pollux.thymeleaf.shiro.dialect.ShiroDialect; /** * shiro配置类 * * @author lit * */ @Configuration public class ShiroConfiguration { private static final Logger logger = LoggerFactory.getLogger(ShiroConfiguration.class); /** * LifecycleBeanPostProcessor,这是个DestructionAwareBeanPostProcessor的子类, * 负责org.apache.shiro.util.Initializable类型bean的生命周期的,初始化和销毁。 * 主要是AuthorizingRealm类的子类,以及EhCacheManager类。 * * @return */ @Bean(name = "lifecycleBeanPostProcessor") public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() { logger.info("ShiroConfiguration.getLifecycleBeanPostProcessor()"); return new LifecycleBeanPostProcessor(); } /** * HashedCredentialsMatcher,这个类是为了对密码进行编码的,防止密码在数据库里明码保存, * 当然在登陆认证的生活,这个类也负责对form里输入的密码进行编码。 * * @return */ // @Bean(name = "hashedCredentialsMatcher") // public HashedCredentialsMatcher hashedCredentialsMatcher() { // HashedCredentialsMatcher credentialsMatcher = new // HashedCredentialsMatcher(); // credentialsMatcher.setHashAlgorithmName("MD5"); // credentialsMatcher.setHashIterations(2); // credentialsMatcher.setStoredCredentialsHexEncoded(true); // return credentialsMatcher; // } /** * ShiroRealm,这是个自定义的认证类,继承自AuthorizingRealm, 负责用户的认证和权限的处理 * * @return */ @Bean(name = "myShiroRealm") @DependsOn("lifecycleBeanPostProcessor") public MyShiroRealm myShiroRealm() { logger.info("ShiroConfiguration.myShiroRealm()"); MyShiroRealm myShiroRealm = new MyShiroRealm(); return myShiroRealm; } /** * EhCacheManager,缓存管理,用户登陆成功后,把用户信息和权限信息缓存起来, * 然后每次用户请求时,放入用户的session中,如果不设置这个bean,每个请求都会查询一次数据库。 * * @return */ @Bean(name = "ehCacheManager") @DependsOn("lifecycleBeanPostProcessor") public EhCacheManager ehCacheManager() { logger.info("ShiroConfiguration.ehCacheManager()"); EhCacheManager cacheManager = new EhCacheManager(); cacheManager.setCacheManagerConfigFile("classpath:config/ehcache-shiro.xml"); return cacheManager; } @Bean(name = "rememberMeCookie") public SimpleCookie rememberMeCookie() { logger.info("ShiroConfiguration.rememberMeCookie()"); // 这个参数是cookie的名称,对应前端的checkbox的name = rememberMe SimpleCookie simpleCookie = new SimpleCookie("rememberMe"); // <!-- 记住我cookie生效时间30天 ,单位秒;--> simpleCookie.setMaxAge(259200); return simpleCookie; } /** * cookie管理对象; * * @return */ @Bean(name = "rememberMeManager") public CookieRememberMeManager rememberMeManager() { logger.info("ShiroConfiguration.rememberMeManager()"); CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager(); cookieRememberMeManager.setCookie(rememberMeCookie()); return cookieRememberMeManager; } /** * SecurityManager,权限管理,这个类组合了登陆,登出,权限,session的处理,是个比较重要的类。 * * @return */ @Bean(name = "securityManager") public DefaultWebSecurityManager securityManager() { logger.info("ShiroConfiguration.getDefaultWebSecurityManager()"); DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); // 设置realm. securityManager.setRealm(myShiroRealm()); // <!-- 用户授权/认证信息Cache, 采用EhCache 缓存 --> securityManager.setCacheManager(ehCacheManager()); //注入记住我管理器; securityManager.setRememberMeManager(rememberMeManager()); return securityManager; } /** * ShiroFilterFactoryBean,是个factorybean,为了生成ShiroFilter。 * 它主要保持了三项数据,securityManager,filters,filterChainDefinitionManager。 * * @return */ @Bean public ShiroFilterFactoryBean shiroFilter() { logger.info("ShiroConfiguration.shiroFilter()"); ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); // 必须设置SecuritManager shiroFilterFactoryBean.setSecurityManager(securityManager()); Map<String, Filter> filtersMap = shiroFilterFactoryBean.getFilters(); filtersMap.put("authc", myFormAuthenticationFilter());// 自定义拦截器 shiroFilterFactoryBean.setFilters(filtersMap); // 拦截器 Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>(); // 配置退出过滤器,其中的具体代码Shiro已经替我们实现了 filterChainDefinitionMap.put("/logout", "logout"); filterChainDefinitionMap.put("/css/**", "anon"); filterChainDefinitionMap.put("/js/**", "anon"); filterChainDefinitionMap.put("/img/**", "anon"); // <!-- 过滤链定义,从上向下顺序执行,一般将 /**放在最为下边 -->:这是一个坑呢,一不小心代码就不好使了; // <!-- authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问--> filterChainDefinitionMap.put("/logout", "logout"); filterChainDefinitionMap.put("/index", "authc"); filterChainDefinitionMap.put("/**", "authc"); // 如果不设置默认会自动寻找工程根目录下的"/login"页面 shiroFilterFactoryBean.setLoginUrl("/login"); // 登录成功后要跳转的链接 shiroFilterFactoryBean.setSuccessUrl("/index"); // 未授权界面; shiroFilterFactoryBean.setUnauthorizedUrl("/403"); // 加载shiroFilter权限控制规则 shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); return shiroFilterFactoryBean; } @Bean public MyFormAuthenticationFilter myFormAuthenticationFilter() { MyFormAuthenticationFilter myFormAuthenticationFilter = new MyFormAuthenticationFilter(); return myFormAuthenticationFilter; } /** * DefaultAdvisorAutoProxyCreator,Spring的一个bean,由Advisor决定对哪些类的方法进行AOP代理。 * * @return */ @Bean @DependsOn("lifecycleBeanPostProcessor") public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() { logger.info("ShiroConfiguration.defaultAdvisorAutoProxyCreator()"); DefaultAdvisorAutoProxyCreator daap = new DefaultAdvisorAutoProxyCreator(); daap.setProxyTargetClass(true); return daap; } /** * AuthorizationAttributeSourceAdvisor,shiro里实现的Advisor类, * 内部使用AopAllianceAnnotationsAuthorizingMethodInterceptor来拦截用以下注解的方法。 * 老实说,这里注入securityManager,我不知道有啥用,从source上看不出它在什么地方会被调用。 * * @return */ @Bean public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor() { logger.info("ShiroConfiguration.authorizationAttributeSourceAdvisor()"); AuthorizationAttributeSourceAdvisor aasa = new AuthorizationAttributeSourceAdvisor(); aasa.setSecurityManager(securityManager()); return aasa; } /** * ShiroDialect,为了在thymeleaf里使用shiro的标签的bean * * @return */ @Bean(name = "shiroDialect") public ShiroDialect shiroDialect() { return new ShiroDialect(); } }
thymleaf使用shiro标签,需要引入
<dependency> <groupId>com.github.theborakompanioni</groupId> <artifactId>thymeleaf-extras-shiro</artifactId> <version>1.2.1</version> </dependency>
注:问题:https://www.oschina.net/question/250720_195683
FilterChain修改如下:
// 拦截器 Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>(); // <!-- 过滤链定义,从上向下顺序执行,一般将 /**放在最为下边 -->:这是一个坑呢,一不小心代码就不好使了; // <!-- authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问--> // 配置退出过滤器,其中的具体代码Shiro已经替我们实现了 filterChainDefinitionMap.put("/", "authc"); filterChainDefinitionMap.put("/index", "authc"); filterChainDefinitionMap.put("/logout", "logout"); //filterChainDefinitionMap.put("/**", "anon"); filterChainDefinitionMap.put("/sys/**", "authc"); filterChainDefinitionMap.put("/css/**", "anon"); filterChainDefinitionMap.put("/js/**", "anon"); filterChainDefinitionMap.put("/images/**", "anon"); filterChainDefinitionMap.put("/vendors/**", "anon"); filterChainDefinitionMap.put("/fonts/**", "anon"); // 加载shiroFilter权限控制规则 shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);