ShiroConfig.java 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379
  1. package platform.config.shiro;
  2. import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
  3. import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
  4. import org.apache.shiro.cache.CacheManager;
  5. import org.apache.shiro.cache.ehcache.EhCacheManager;
  6. import org.apache.shiro.mgt.SecurityManager;
  7. import org.apache.shiro.session.mgt.ExecutorServiceSessionValidationScheduler;
  8. import org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO;
  9. import org.apache.shiro.session.mgt.eis.JavaUuidSessionIdGenerator;
  10. import org.apache.shiro.spring.LifecycleBeanPostProcessor;
  11. import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
  12. import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
  13. import org.apache.shiro.web.filter.authc.LogoutFilter;
  14. import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
  15. import org.apache.shiro.web.servlet.SimpleCookie;
  16. import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
  17. import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
  18. import org.springframework.beans.factory.config.MethodInvokingFactoryBean;
  19. import org.springframework.cache.ehcache.EhCacheManagerFactoryBean;
  20. import org.springframework.context.annotation.Bean;
  21. import org.springframework.context.annotation.Configuration;
  22. import org.springframework.context.annotation.DependsOn;
  23. import platform.modules.sys.log.service.LogService;
  24. import platform.modules.sys.shiro.AuthenticationRealm;
  25. import platform.modules.sys.shiro.CredentialsMatcher;
  26. import platform.modules.sys.shiro.DefaultFormAuthenticationFilter;
  27. import platform.modules.sys.shiro.filter.LoginFilter;
  28. import platform.modules.sys.shiro.filter.SystemLogoutFilter;
  29. import platform.modules.sys.shiro.filter.TokenFilter;
  30. import javax.servlet.Filter;
  31. import java.util.LinkedHashMap;
  32. import java.util.Map;
  33. /**
  34. * Shiro配置
  35. *
  36. * @author lhf
  37. */
  38. @Configuration
  39. public class ShiroConfig {
  40. /**
  41. * ShiroFilterFactoryBean 处理拦截资源文件问题。
  42. * 注意:单独一个ShiroFilterFactoryBean配置是或报错的,以为在
  43. * 初始化ShiroFilterFactoryBean的时候需要注入:SecurityManager
  44. * <p>
  45. * Filter Chain定义说明
  46. * 1、一个URL可以配置多个Filter,使用逗号分隔
  47. * 2、当设置多个过滤器时,全部验证通过,才视为通过
  48. * 3、部分过滤器可指定参数,如perms,roles
  49. */
  50. @Bean(name = "shiroFilter")
  51. public ShiroFilterFactoryBean getShiroFilterFactoryBean(SecurityManager securityManager, LogService logService) {
  52. ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
  53. // 必须设置 SecurityManager
  54. shiroFilterFactoryBean.setSecurityManager(securityManager);
  55. // 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面
  56. // shiroFilterFactoryBean.setLoginUrl("/home");
  57. shiroFilterFactoryBean.setLoginUrl("/index");
  58. // 登录成功后要跳转的链接
  59. // shiroFilterFactoryBean.setSuccessUrl("/admin/home");
  60. //未授权界面,注:注解方式验证权限不好使;
  61. // shiroFilterFactoryBean.setUnauthorizedUrl("/admin/403");
  62. //自定义登出过滤器,设置登出后跳转地址
  63. Map<String, Filter> filters = new LinkedHashMap<String, Filter>();
  64. //自定义登录过滤器
  65. filters.put("myLogin", loginFilter());
  66. //自定义限制同一账号登录数量filter
  67. //自定义退出跳转页面
  68. LogoutFilter logoutFilter = new SystemLogoutFilter(logService);
  69. //logoutFilter.setRedirectUrl("/admin/login");
  70. //logoutFilter.setRedirectUrl("/home/login");
  71. logoutFilter.setRedirectUrl("/index");
  72. filters.put("myLogout", logoutFilter);
  73. filters.put("authc", new DefaultFormAuthenticationFilter(logService));
  74. //手机端退出登录跳转页面
  75. LogoutFilter mobileLogoutFilter = new SystemLogoutFilter(logService);
  76. mobileLogoutFilter.setRedirectUrl("/mobile/login");
  77. filters.put("mobileLogout", mobileLogoutFilter);
  78. //新门户退出
  79. LogoutFilter platformLogout = new SystemLogoutFilter(logService);
  80. mobileLogoutFilter.setRedirectUrl("/index");
  81. filters.put("platformLogout", platformLogout);
  82. //门户工业载体过滤器
  83. filters.put("industry", new TokenFilter());
  84. shiroFilterFactoryBean.setFilters(filters);
  85. //过虑器链定义,从上向下顺序执行,一般将/**放在最下边
  86. Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
  87. //配置退出过滤器,其中的具体的退出代码Shiro已经替我们实现了
  88. filterChainDefinitionMap.put("/admin/logout", "myLogout");
  89. //配置退出过滤器-手机端
  90. filterChainDefinitionMap.put("/mobile/logout", "mobileLogout");
  91. //配置退出过滤器-新门户
  92. filterChainDefinitionMap.put("/platform/logout", "platformLogout");
  93. //登录请求匿名访问
  94. filterChainDefinitionMap.put("/admin/login", "myLogin");
  95. filterChainDefinitionMap.put("/mobile/login", "myLogin");
  96. filterChainDefinitionMap.put("/home/login", "myLogin");
  97. //过滤链定义,从上向下顺序执行,一般将放在最为下边:这是一个坑呢,一不小心代码就不好使了;
  98. //authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问
  99. filterChainDefinitionMap.put("/government/activity/getAllEvents", "anon");
  100. filterChainDefinitionMap.put("/government/activity/getEventList", "anon");
  101. filterChainDefinitionMap.put("/project/**", "authc");
  102. filterChainDefinitionMap.put("/projectDeclaration/**", "authc");
  103. filterChainDefinitionMap.put("/admin/**", "authc");
  104. filterChainDefinitionMap.put("/government/**", "authc");
  105. filterChainDefinitionMap.put("/build/**", "authc");
  106. filterChainDefinitionMap.put("/mobile/**", "authc");
  107. filterChainDefinitionMap.put("/super/**", "authc");
  108. filterChainDefinitionMap.put("/street/**", "authc");
  109. filterChainDefinitionMap.put("/common/index", "authc");
  110. filterChainDefinitionMap.put("/export/*", "authc");
  111. filterChainDefinitionMap.put("/area/*", "authc");
  112. filterChainDefinitionMap.put("/stockLand/**", "authc");
  113. filterChainDefinitionMap.put("/projectApplication/**", "authc");
  114. filterChainDefinitionMap.put("/projectApprove/**", "authc");
  115. filterChainDefinitionMap.put("/upload/*", "anon");
  116. filterChainDefinitionMap.put("/message/getMyRemind", "authc");
  117. filterChainDefinitionMap.put("/platform/streets", "anon");
  118. filterChainDefinitionMap.put("/carrier/checkCarrier", "anon");
  119. filterChainDefinitionMap.put("/community/streets", "anon");
  120. //工业载体
  121. filterChainDefinitionMap.put("/community/*", "industry");
  122. filterChainDefinitionMap.put("/carrier/*", "industry");
  123. filterChainDefinitionMap.put("/map/api/investments/*", "industry");
  124. filterChainDefinitionMap.put("/contract/export", "anon");
  125. filterChainDefinitionMap.put("/contract/*", "industry");
  126. filterChainDefinitionMap.put("/investment/*", "industry");
  127. filterChainDefinitionMap.put("/investment", "industry");
  128. filterChainDefinitionMap.put("/front/investment/*", "industry");
  129. filterChainDefinitionMap.put("/intention/*", "industry");
  130. filterChainDefinitionMap.put("/rental", "industry");
  131. filterChainDefinitionMap.put("/rental/**", "industry");
  132. // filterChainDefinitionMap.put("/rentals", "industry");
  133. //filterChainDefinitionMap.put("/*", "authc");
  134. shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
  135. return shiroFilterFactoryBean;
  136. }
  137. /**
  138. * securityManager安全管理器
  139. * Shiro的核心安全接口,这个属性是必须的
  140. *
  141. * @return
  142. */
  143. @Bean(name = "securityManager")
  144. public SecurityManager getSecurityManager(EhCacheManagerFactoryBean ehCacheManagerFactoryBean,
  145. RetryLimitCredentialsMatcher retryLimitCredentialsMatcher) {
  146. DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
  147. //注入自定义Realm
  148. securityManager.setRealm(getAuthenticationRealm(retryLimitCredentialsMatcher));
  149. //注入缓存管理器
  150. securityManager.setCacheManager(getCacheShiroManage(ehCacheManagerFactoryBean));
  151. //注入session管理器
  152. securityManager.setSessionManager(getSessionManage());
  153. return securityManager;
  154. }
  155. /**
  156. * 自定义身份认证realm;
  157. *
  158. * @return
  159. */
  160. @Bean
  161. public AuthenticationRealm getAuthenticationRealm(RetryLimitCredentialsMatcher retryLimitCredentialsMatcher) {
  162. AuthenticationRealm authenticationRealm = new AuthenticationRealm();
  163. //将凭证匹配器设置到realm中,realm按照凭证匹配器的要求进行散列
  164. // authenticationRealm.setCredentialsMatcher(getHashedCredentialsMatcher());
  165. authenticationRealm.setCredentialsMatcher(retryLimitCredentialsMatcher);
  166. //配置缓存
  167. //开启缓存
  168. authenticationRealm.setCachingEnabled(true);
  169. //开启认证缓存
  170. authenticationRealm.setAuthenticationCachingEnabled(false);
  171. //设置认证缓存的名称对应ehcache中配置
  172. // authenticationRealm.setAuthenticationCacheName("goodAuthenticationCache");
  173. //开启授权信息缓存
  174. authenticationRealm.setAuthorizationCachingEnabled(true);
  175. //设置授权缓存的名称对应ehcache中配置
  176. authenticationRealm.setAuthorizationCacheName("goodAuthorizationCache");
  177. return authenticationRealm;
  178. }
  179. // /**
  180. // * 凭证匹配器 指定密码匹配规则
  181. // *
  182. // * @return
  183. // */
  184. // @Bean(name = "hashedCredentialsMatcher")
  185. // public HashedCredentialsMatcher getHashedCredentialsMatcher() {
  186. // CredentialsMatcher credentialsMatcher = new CredentialsMatcher();
  187. // credentialsMatcher.setHashAlgorithmName("MD5");//散列算法:这里使用MD5算法;
  188. // credentialsMatcher.setHashIterations(1); //散列的次数,比如散列两次,相当于 md5(md5(""));
  189. // credentialsMatcher.setStoredCredentialsHexEncoded(true);
  190. // return credentialsMatcher;
  191. // }
  192. /**
  193. * Shiro生命周期处理器
  194. * 保证实现了Shiro内部lifecycle函数的bean执行
  195. *
  196. * @return
  197. */
  198. @Bean(name = "lifecycleBeanPostProcessor")
  199. public LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
  200. return new LifecycleBeanPostProcessor();
  201. }
  202. /**
  203. * 会话管理器
  204. *
  205. * @return
  206. */
  207. @Bean(name = "sessionManager")
  208. public DefaultWebSessionManager getSessionManage() {
  209. DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
  210. //session的失效时长,单位毫秒
  211. sessionManager.setGlobalSessionTimeout(3600000); //60分钟失效
  212. sessionManager.setSessionValidationScheduler(getExecutorServiceSessionValidationScheduler());
  213. sessionManager.setSessionValidationSchedulerEnabled(true);
  214. //删除失效的session
  215. sessionManager.setDeleteInvalidSessions(true);
  216. sessionManager.setSessionIdCookieEnabled(true);
  217. sessionManager.setSessionIdCookie(getSessionIdCookie());
  218. sessionManager.setSessionDAO(getSessionDao());
  219. //去除浏览器地址栏中url中JSESSIONID参数
  220. sessionManager.setSessionIdUrlRewritingEnabled(false);
  221. // -----可以添加session 创建、删除的监听器
  222. return sessionManager;
  223. }
  224. /**
  225. * 会话DAO
  226. *
  227. * @return
  228. */
  229. @Bean(name = "sessionDao")
  230. public EnterpriseCacheSessionDAO getSessionDao() {
  231. EnterpriseCacheSessionDAO sessionDAO = new EnterpriseCacheSessionDAO();
  232. sessionDAO.setActiveSessionsCacheName("shiro-activeSessionCache");
  233. sessionDAO.setSessionIdGenerator(getSessionIdGenerator());
  234. return sessionDAO;
  235. }
  236. /**
  237. * 会话ID生成器
  238. *
  239. * @return
  240. */
  241. @Bean(name = "sessionIdGenerator")
  242. public JavaUuidSessionIdGenerator getSessionIdGenerator() {
  243. JavaUuidSessionIdGenerator sessionIdGenerator = new JavaUuidSessionIdGenerator();
  244. return sessionIdGenerator;
  245. }
  246. /**
  247. * 缓存管理器 使用Ehcache实现
  248. *
  249. * @return
  250. */
  251. @Bean(name = "cacheShiroManager")
  252. public CacheManager getCacheShiroManage(EhCacheManagerFactoryBean ehCacheManagerFactoryBean) {
  253. EhCacheManager ehCacheManager = new EhCacheManager();
  254. // ehCacheManager.setCacheManagerConfigFile("classpath:ehcache-shiro.xml");
  255. ehCacheManager.setCacheManager(ehCacheManagerFactoryBean.getObject());
  256. return ehCacheManager;
  257. }
  258. @Bean
  259. public RetryLimitCredentialsMatcher getRetryLimit(CacheManager cacheManager){
  260. RetryLimitCredentialsMatcher retryLimitCredentialsMatcher = new RetryLimitCredentialsMatcher(cacheManager);
  261. retryLimitCredentialsMatcher.setHashAlgorithmName(ShiroKit.HASH_ALGORITHM_NAME);
  262. retryLimitCredentialsMatcher.setHashIterations(ShiroKit.HASHITERATIONS);
  263. retryLimitCredentialsMatcher.setStoredCredentialsHexEncoded(true);
  264. return retryLimitCredentialsMatcher;
  265. }
  266. /**
  267. * 会话Cookie模板
  268. *
  269. * @return
  270. */
  271. @Bean(name = "sessionIdCookie")
  272. public SimpleCookie getSessionIdCookie() {
  273. SimpleCookie cookie = new SimpleCookie("sid");
  274. cookie.setHttpOnly(true);
  275. cookie.setMaxAge(-1);
  276. return cookie;
  277. }
  278. /**
  279. * 会话验证调度器
  280. *
  281. * @return
  282. */
  283. @Bean(name = "sessionValidationScheduler")
  284. public ExecutorServiceSessionValidationScheduler getExecutorServiceSessionValidationScheduler() {
  285. ExecutorServiceSessionValidationScheduler scheduler = new ExecutorServiceSessionValidationScheduler();
  286. scheduler.setInterval(3600000);//每隔60分钟验证清理失效的session
  287. return scheduler;
  288. }
  289. /**
  290. * 相当于调用SecurityUtils.setSecurityManager(securityManager)
  291. *
  292. * @return
  293. */
  294. @Bean
  295. public MethodInvokingFactoryBean getMethodInvokingFactoryBean(EhCacheManagerFactoryBean ehCacheManagerFactoryBean,
  296. RetryLimitCredentialsMatcher retryLimitCredentialsMatcher) {
  297. MethodInvokingFactoryBean factoryBean = new MethodInvokingFactoryBean();
  298. factoryBean.setStaticMethod("org.apache.shiro.SecurityUtils.setSecurityManager");
  299. factoryBean.setArguments(new Object[]{getSecurityManager(ehCacheManagerFactoryBean, retryLimitCredentialsMatcher)});
  300. return factoryBean;
  301. }
  302. /**
  303. * 开启Shiro的注解(如@RequiresRoles,@RequiresPermissions),需借助SpringAOP扫描使用Shiro注解的类,并在必要时进行安全逻辑验证
  304. * 配置以下两个bean即可实现此功能
  305. *
  306. * @return
  307. */
  308. @Bean
  309. @DependsOn("lifecycleBeanPostProcessor")
  310. public DefaultAdvisorAutoProxyCreator getAutoProxyCreator() {
  311. DefaultAdvisorAutoProxyCreator creator = new DefaultAdvisorAutoProxyCreator();
  312. creator.setProxyTargetClass(true);
  313. return creator;
  314. }
  315. @Bean
  316. public AuthorizationAttributeSourceAdvisor getAuthorizationAttributeSourceAdvisor(EhCacheManagerFactoryBean ehCacheManagerFactoryBean,
  317. RetryLimitCredentialsMatcher retryLimitCredentialsMatcher) {
  318. AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
  319. advisor.setSecurityManager(getSecurityManager(ehCacheManagerFactoryBean, retryLimitCredentialsMatcher));
  320. return advisor;
  321. }
  322. /*
  323. * @methodName: loginFilter
  324. * @param: []
  325. * @description:登录过滤器
  326. * @return: com.jk.shiro.LoginFilter
  327. * @author: cuiP
  328. * @date: 2017/7/28 16:27
  329. * @version: V1.0.0
  330. */
  331. @Bean
  332. public LoginFilter loginFilter() {
  333. return new LoginFilter();
  334. }
  335. /**
  336. * ShiroDialect,为了在thymeleaf里使用shiro的标签的bean
  337. *
  338. * @return
  339. */
  340. @Bean
  341. public ShiroDialect shiroDialect() {
  342. return new ShiroDialect();
  343. }
  344. }