//druid連接池配置 @Configuration public class DruidConfig { @Bean public ServletRegistrationBean druidServlet() { ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(new StatViewServlet(), "/druid/*"); // 登錄查看信息的賬號密碼. servletRegistrationBean.addInitParameter("loginUsername", "admin"); servletRegistrationBean.addInitParameter("loginPassword", "123456"); return servletRegistrationBean; } @Bean public FilterRegistrationBean filterRegistrationBean() { FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(); filterRegistrationBean.setFilter(new WebStatFilter()); filterRegistrationBean.addUrlPatterns("/*"); filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*"); return filterRegistrationBean; } }
@Configuration @EnableCaching//開啟換成配置 public class RedisConfig extends CachingConfigurerSupport { private static Logger Logger = LoggerFactory.getLogger(RedisConfig.class); @Value("${spring.redis.host}") private String host; @Value("${spring.redis.port}") private int port; @Value("${spring.redis.timeout}") private int timeout; @Value("${spring.redis.pool.max-idle}") private int maxIdle; @Value("${spring.redis.pool.max-wait}") private long maxWaitMillis; @Bean public JedisPool redisPoolFactory() { Logger.info("開啟redis,redis地址:" + host + ":" + port + ",JedisPool注入成功!!"); JedisPoolConfig jedisPoolConfig = new JedisPoolConfig(); jedisPoolConfig.setMaxIdle(maxIdle); jedisPoolConfig.setMaxWaitMillis(maxWaitMillis); JedisPool jedisPool = new JedisPool(jedisPoolConfig, host, port, timeout); return jedisPool; } /** * 配置shiro redisManager 使用的是shiro-redis開源插件 * * @return */ @Bean public RedisManager redisManager() { RedisManager redisManager = new RedisManager(); redisManager.setHost(host); redisManager.setPort(port); redisManager.setExpire(1800);// 配置緩存過期時間 redisManager.setTimeout(timeout); return redisManager; } }
@Configuration public class ShiroConfig { /** * 緩存和session的管理 */ @Autowired private ShiroSessionAndCache shiroSessionAndCache; /** * shiro 服務 */ @Autowired private ShiroService shiroService; private static Logger Logger = LoggerFactory.getLogger(ShiroConfig.class); @Bean public static LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() { return new LifecycleBeanPostProcessor(); } /** * ShiroDialect,為了在thymeleaf里使用shiro的標簽的bean * @return */ @Bean public ShiroDialect shiroDialect() { return new ShiroDialect(); } /** * ShiroFilterFactoryBean 處理攔截資源文件問題。 注意:單獨一個ShiroFilterFactoryBean配置是或報錯的,因為在 * 初始化ShiroFilterFactoryBean的時候需要注入:SecurityManager Filter Chain定義說明 * 1、一個URL可以配置多個Filter,使用逗號分隔 * 2、當設置多個過濾器時,全部驗證通過,才視為通過 * 3、部分過濾器可指定參數,如perms,roles */ @Bean public ShiroFilterFactoryBean shirFilter(org.apache.shiro.mgt.SecurityManager securityManager) { Logger.info("ShiroConfiguration.shirFilter()"); ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); // 必須設置 SecurityManager shiroFilterFactoryBean.setSecurityManager(securityManager); // 如果不設置默認會自動尋找Web工程根目錄下的"/login"頁面 shiroFilterFactoryBean.setLoginUrl("/login"); //登錄頁面 // 登錄成功后要跳轉的鏈接 shiroFilterFactoryBean.setSuccessUrl("/index");//首頁 // 未授權界面; shiroFilterFactoryBean.setUnauthorizedUrl("/403");//錯誤頁面 // 攔截器. 權限配置 Map<String, String> filterChainDefinitionMap = shiroService.loadFilterChainDefinitions(); shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); return shiroFilterFactoryBean; } @Bean public org.apache.shiro.mgt.SecurityManager securityManager() { DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); // 設置realm. securityManager.setRealm(myShiroRealm()); // 自定義緩存實現 使用redis ,生產環境才需要這么設置,開發環境需要清空全選,所以不建議開啟這個 // securityManager.setCacheManager(cacheManager()); // 自定義session管理 使用redis securityManager.setSessionManager(shiroSessionAndCache.sessionManager()); return securityManager; } @Bean public ZxShiroRealm myShiroRealm() { ZxShiroRealm myShiroRealm = new ZxShiroRealm(); myShiroRealm.setCredentialsMatcher(hashedCredentialsMatcher()); return myShiroRealm; } /** * 憑證匹配器 (由於我們的密碼校驗交給Shiro的SimpleAuthenticationInfo進行處理了 * 所以我們需要修改下doGetAuthenticationInfo中的代碼; ) * @return */ @Bean public HashedCredentialsMatcher hashedCredentialsMatcher() { HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher(); hashedCredentialsMatcher.setHashAlgorithmName("md5");// 散列算法:這里使用MD5算法; hashedCredentialsMatcher.setHashIterations(2);// 散列的次數,比如散列兩次,相當於 md5(md5("")); return hashedCredentialsMatcher; } /** * 開啟shiro aop注解支持. 使用代理方式;所以需要開啟代碼支持; * * @param securityManager * @return */ @Bean public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(org.apache.shiro.mgt.SecurityManager securityManager) { AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor(); authorizationAttributeSourceAdvisor.setSecurityManager(securityManager); return authorizationAttributeSourceAdvisor; } @Bean public RedisSessionDAO redisSessionDAO() { return shiroSessionAndCache.redisSessionDAO(); } @Bean public DefaultWebSessionManager sessionManager() { return shiroSessionAndCache.sessionManager(); } /** * 注冊DelegatingFilterProxy(Shiro) * 集成Shiro有2種方法: * 1. 按這個方法自己組裝一個FilterRegistrationBean(這種方法更為靈活,可以自己定義UrlPattern, * 在項目使用中你可能會因為一些很但疼的問題最后采用它, 想使用它你可能需要看官網或者已經很了解Shiro的處理原理了) * 2. 直接使用ShiroFilterFactoryBean(這種方法比較簡單,其內部對ShiroFilter做了組裝工作,無法自己定義UrlPattern, * 默認攔截 /*) * * @param dispatcherServlet * @return * @create 2016年1月13日 */ // @Bean // public FilterRegistrationBean filterRegistrationBean() { // FilterRegistrationBean filterRegistration = new FilterRegistrationBean(); // filterRegistration.setFilter(new DelegatingFilterProxy("shiroFilter")); // // 該值缺省為false,表示生命周期由SpringApplicationContext管理,設置為true則表示由ServletContainer管理 // filterRegistration.addInitParameter("targetFilterLifecycle", "true"); // filterRegistration.setEnabled(true); // filterRegistration.addUrlPatterns("/*");// 可以自己靈活的定義很多,避免一些根本不需要被Shiro處理的請求被包含進來 // return filterRegistration; // } }
@Service public class ShiroService { private static Logger Logger = LoggerFactory.getLogger(ShiroService.class); @Autowired private ResourcesService resourcesService; /** * 初始化權限 */ public Map<String, String> loadFilterChainDefinitions() { // 權限控制map.從數據庫獲取 Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>(); // 配置退出 過濾器,其中的具體的退出代碼Shiro已經替我們實現了 filterChainDefinitionMap.put("/logout", "logout"); filterChainDefinitionMap.put("/assets/**", "anon"); filterChainDefinitionMap.put("/css/**", "anon"); filterChainDefinitionMap.put("/js/**", "anon"); filterChainDefinitionMap.put("/img/**", "anon"); filterChainDefinitionMap.put("/font-awesome/**", "anon"); // <!-- 過濾鏈定義,從上向下順序執行,一般將 /**放在最為下邊 -->:這是一個坑呢,一不小心代碼就不好使了; // <!-- authc:所有url都必須認證通過才可以訪問; anon:所有url都都可以匿名訪問--> // 自定義加載權限資源關系 List<Resources> resourcesList = resourcesService.queryAll(); for (Resources resources : resourcesList) { if (StringUtil.isNotEmpty(resources.getResurl())) { String permission = "perms[" + resources.getResurl() + "]"; filterChainDefinitionMap.put(resources.getResurl(), permission); } } filterChainDefinitionMap.put("/**", "authc"); Logger.info("初始化權限配置成功!"); return filterChainDefinitionMap; } }
@Component public class ShiroSessionAndCache { @Autowired private RedisConfig redisConfig; /** * RedisSessionDAO shiro sessionDao層的實現 通過redis 使用的是shiro-redis開源插件 */ public RedisSessionDAO redisSessionDAO() { RedisSessionDAO redisSessionDAO = new RedisSessionDAO(); redisSessionDAO.setRedisManager(redisConfig.redisManager()); return redisSessionDAO; } /** * shiro session的管理 */ public DefaultWebSessionManager sessionManager() { DefaultWebSessionManager sessionManager = new DefaultWebSessionManager(); //session的管理,使用redis來處理session sessionManager.setSessionDAO(redisSessionDAO()); return sessionManager; } /** * cacheManager 緩存 redis實現 使用的是shiro-redis開源插件 * @return */ public RedisCacheManager cacheManager() { RedisCacheManager redisCacheManager = new RedisCacheManager(); redisCacheManager.setRedisManager(redisConfig.redisManager()); return redisCacheManager; } }
@Service public class ShiroPermissionService { private static Logger Logger = LoggerFactory.getLogger(ShiroPermissionService.class); @Autowired private ShiroFilterFactoryBean shiroFilterFactoryBean; @Autowired private RedisSessionDAO redisSessionDAO; @Autowired private ShiroService shiroService; /** * * 此方法描述的是:重新加載權限 刷新緩存 * * @author: Aarony * @version: Nov 13, 2017 10:24:25 AM */ public void updatePermission() { synchronized (shiroFilterFactoryBean) { AbstractShiroFilter shiroFilter = null; try { shiroFilter = (AbstractShiroFilter) shiroFilterFactoryBean.getObject(); } catch (Exception e) { throw new RuntimeException("get ShiroFilter from shiroFilterFactoryBean error!"); } PathMatchingFilterChainResolver filterChainResolver = (PathMatchingFilterChainResolver) shiroFilter.getFilterChainResolver(); DefaultFilterChainManager manager = (DefaultFilterChainManager) filterChainResolver.getFilterChainManager(); // 清空老的權限控制 manager.getFilterChains().clear(); shiroFilterFactoryBean.getFilterChainDefinitionMap().clear(); shiroFilterFactoryBean.setFilterChainDefinitionMap(shiroService.loadFilterChainDefinitions()); // 重新構建生成 Map<String, String> chains = shiroFilterFactoryBean.getFilterChainDefinitionMap(); for (Map.Entry<String, String> entry : chains.entrySet()) { String url = entry.getKey(); String chainDefinition = entry.getValue().trim().replace(" ", ""); manager.createChain(url, chainDefinition); } Logger.info("更新權限成功!"); } } }
具體的shiro 可以看官網或者這個人的博客:https://blog.csdn.net/LHacker/article/details/10438387 寫的蠻詳細的。
具體的shiro 可以看官網或者這個人的博客:https://blog.csdn.net/LHacker/article/details/10438387 寫的蠻詳細的。