content: package net.laoyeye.yyblog.web.config;
  
  import java.util.ArrayList;
  import java.util.Collection;
  import java.util.LinkedHashMap;
  
  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.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.apache.shiro.cache.ehcache.EhCacheManager;
  import org.apache.shiro.codec.Base64;
  import org.apache.shiro.mgt.SecurityManager;
  import org.apache.shiro.session.SessionListener;
  import org.apache.shiro.session.mgt.eis.MemorySessionDAO;
  import org.apache.shiro.session.mgt.eis.SessionDAO;
  
  import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
  import net.laoyeye.yyblog.shiro.realm.UserRealm;
  
  @Configuration
  public class ShiroConfig {
  
      @Bean("lifecycleBeanPostProcessor")
      public static LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
          return new LifecycleBeanPostProcessor();
      }
  
      /**
       * ShiroDialect，为了在thymeleaf里使用shiro的标签的bean
       *
       * @return
       */
      @Bean
      public ShiroDialect shiroDialect() {
          return new ShiroDialect();
      }
  
      @Bean
      ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
          ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
          shiroFilterFactoryBean.setSecurityManager(securityManager);
          shiroFilterFactoryBean.setLoginUrl("/login");
          shiroFilterFactoryBean.setSuccessUrl("/index");
          shiroFilterFactoryBean.setUnauthorizedUrl("/403");
          LinkedHashMap<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
          filterChainDefinitionMap.put("/static/**", "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("/logout", "logout");
          filterChainDefinitionMap.put("/login", "anon");
          filterChainDefinitionMap.put("/", "anon");
          filterChainDefinitionMap.put("/index", "anon");
          filterChainDefinitionMap.put("/next", "anon");
          filterChainDefinitionMap.put("/article/**", "anon");
          filterChainDefinitionMap.put("/about/**", "anon");
          filterChainDefinitionMap.put("/api/**", "anon");
          //因为这里开启了rememberMe，所以要用user,authc是必须认证（执行实际的登陆操作）
         /* filterChainDefinitionMap.put("/**", "authc");*/
          filterChainDefinitionMap.put("/**", "user");  
          shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
          return shiroFilterFactoryBean;
      }
  
  
      @Bean
      public SecurityManager securityManager() {
          DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
          // 自定义缓存实现 使用EhCache
          securityManager.setCacheManager(ehCacheManager());
          //设置realm.
          securityManager.setRealm(userRealm());
          securityManager.setRememberMeManager(rememberMeManager());
          securityManager.setSessionManager(sessionManager());
          return securityManager;
      }
  
      @Bean
      UserRealm userRealm() {
          UserRealm userRealm = new UserRealm();
          return userRealm;
      }
      /**
       * 开启shiro aop注解支持.
       * 使用代理方式;所以需要开启代码支持;
       */
      @Bean  
      @DependsOn({"lifecycleBeanPostProcessor"})  
      public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator(){  
          DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();  
          advisorAutoProxyCreator.setProxyTargetClass(true);  
          return advisorAutoProxyCreator;  
      }  
  
      /**
       * 开启shiro aop注解支持.
       * 使用代理方式;所以需要开启代码支持;
       *
       * @param securityManager
       * @return
       */
      @Bean
      public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
          AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
          authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
          return authorizationAttributeSourceAdvisor;
      }
  
      @Bean
      public SessionDAO sessionDAO() {
          
          return new MemorySessionDAO();
      }
  
      /**
       * shiro session的管理
       */
      @Bean
      public DefaultWebSessionManager sessionManager() {
          DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
          sessionManager.setSessionDAO(sessionDAO());
          Collection<SessionListener> listeners = new ArrayList<SessionListener>();
          sessionManager.setSessionListeners(listeners);
          return sessionManager;
      }
      
      @Bean
      public EhCacheManager ehCacheManager() {
          EhCacheManager em = new EhCacheManager();
          em.setCacheManagerConfigFile("classpath:config/ehcache.xml");
          return em;
      }
      
      /**
      * cookie管理器;
      * @return
      */
      @Bean
      public CookieRememberMeManager rememberMeManager(){
          CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
          //rememberme cookie加密的密钥 建议每个项目都不一样 默认AES算法 密钥长度（128 256 512 位），通过以下代码可以获取
          //KeyGenerator keygen = KeyGenerator.getInstance("AES");
          //SecretKey deskey = keygen.generateKey();
          //System.out.println(Base64.encodeToString(deskey.getEncoded()));
          byte[] cipherKey = Base64.decode("wGiHplamyXlVB11UXWol8g==");
          cookieRememberMeManager.setCipherKey(cipherKey);
          cookieRememberMeManager.setCookie(rememberMeCookie());
          return cookieRememberMeManager;
      }
      
      @Bean
      public SimpleCookie rememberMeCookie(){
          //这个参数是cookie的名称，对应前端的checkbox的name = rememberMe
          SimpleCookie simpleCookie = new SimpleCookie("rememberMe");
          //如果httyOnly设置为true，则客户端不会暴露给客户端脚本代码，使用HttpOnly cookie有助于减少某些类型的跨站点脚本攻击；
          simpleCookie.setHttpOnly(true);
          //记住我cookie生效时间,默认30天 ,单位秒：60 * 60 * 24 * 30
          simpleCookie.setMaxAge(259200);
          return simpleCookie;
      }
  
  
  }