ShiroConfig.java 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  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/*", "industry");
  125. filterChainDefinitionMap.put("/investment/*", "industry");
  126. filterChainDefinitionMap.put("/investment", "industry");
  127. filterChainDefinitionMap.put("/front/investment/*", "industry");
  128. filterChainDefinitionMap.put("/intention/*", "industry");
  129. filterChainDefinitionMap.put("/rental", "industry");
  130. filterChainDefinitionMap.put("/rental/**", "industry");
  131. // filterChainDefinitionMap.put("/rentals", "industry");
  132. //filterChainDefinitionMap.put("/*", "authc");
  133. shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
  134. return shiroFilterFactoryBean;
  135. }
  136. /**
  137. * securityManager安全管理器
  138. * Shiro的核心安全接口,这个属性是必须的
  139. *
  140. * @return
  141. */
  142. @Bean(name = "securityManager")
  143. public SecurityManager getSecurityManager(EhCacheManagerFactoryBean ehCacheManagerFactoryBean) {
  144. DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
  145. //注入自定义Realm
  146. securityManager.setRealm(getAuthenticationRealm());
  147. //注入缓存管理器
  148. securityManager.setCacheManager(getCacheShiroManage(ehCacheManagerFactoryBean));
  149. //注入session管理器
  150. securityManager.setSessionManager(getSessionManage());
  151. return securityManager;
  152. }
  153. /**
  154. * 自定义身份认证realm;
  155. *
  156. * @return
  157. */
  158. @Bean
  159. public AuthenticationRealm getAuthenticationRealm() {
  160. AuthenticationRealm authenticationRealm = new AuthenticationRealm();
  161. //将凭证匹配器设置到realm中,realm按照凭证匹配器的要求进行散列
  162. authenticationRealm.setCredentialsMatcher(getHashedCredentialsMatcher());
  163. //配置缓存
  164. //开启缓存
  165. authenticationRealm.setCachingEnabled(true);
  166. //开启认证缓存
  167. authenticationRealm.setAuthenticationCachingEnabled(false);
  168. //设置认证缓存的名称对应ehcache中配置
  169. // authenticationRealm.setAuthenticationCacheName("goodAuthenticationCache");
  170. //开启授权信息缓存
  171. authenticationRealm.setAuthorizationCachingEnabled(true);
  172. //设置授权缓存的名称对应ehcache中配置
  173. authenticationRealm.setAuthorizationCacheName("goodAuthorizationCache");
  174. return authenticationRealm;
  175. }
  176. /**
  177. * 凭证匹配器 指定密码匹配规则
  178. *
  179. * @return
  180. */
  181. @Bean(name = "hashedCredentialsMatcher")
  182. public HashedCredentialsMatcher getHashedCredentialsMatcher() {
  183. CredentialsMatcher credentialsMatcher = new CredentialsMatcher();
  184. credentialsMatcher.setHashAlgorithmName("MD5");//散列算法:这里使用MD5算法;
  185. credentialsMatcher.setHashIterations(1); //散列的次数,比如散列两次,相当于 md5(md5(""));
  186. credentialsMatcher.setStoredCredentialsHexEncoded(true);
  187. return credentialsMatcher;
  188. }
  189. /**
  190. * Shiro生命周期处理器
  191. * 保证实现了Shiro内部lifecycle函数的bean执行
  192. *
  193. * @return
  194. */
  195. @Bean(name = "lifecycleBeanPostProcessor")
  196. public LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
  197. return new LifecycleBeanPostProcessor();
  198. }
  199. /**
  200. * 会话管理器
  201. *
  202. * @return
  203. */
  204. @Bean(name = "sessionManager")
  205. public DefaultWebSessionManager getSessionManage() {
  206. DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
  207. //session的失效时长,单位毫秒
  208. sessionManager.setGlobalSessionTimeout(3600000); //60分钟失效
  209. sessionManager.setSessionValidationScheduler(getExecutorServiceSessionValidationScheduler());
  210. sessionManager.setSessionValidationSchedulerEnabled(true);
  211. //删除失效的session
  212. sessionManager.setDeleteInvalidSessions(true);
  213. sessionManager.setSessionIdCookieEnabled(true);
  214. sessionManager.setSessionIdCookie(getSessionIdCookie());
  215. sessionManager.setSessionDAO(getSessionDao());
  216. //去除浏览器地址栏中url中JSESSIONID参数
  217. sessionManager.setSessionIdUrlRewritingEnabled(false);
  218. // -----可以添加session 创建、删除的监听器
  219. return sessionManager;
  220. }
  221. /**
  222. * 会话DAO
  223. *
  224. * @return
  225. */
  226. @Bean(name = "sessionDao")
  227. public EnterpriseCacheSessionDAO getSessionDao() {
  228. EnterpriseCacheSessionDAO sessionDAO = new EnterpriseCacheSessionDAO();
  229. sessionDAO.setActiveSessionsCacheName("shiro-activeSessionCache");
  230. sessionDAO.setSessionIdGenerator(getSessionIdGenerator());
  231. return sessionDAO;
  232. }
  233. /**
  234. * 会话ID生成器
  235. *
  236. * @return
  237. */
  238. @Bean(name = "sessionIdGenerator")
  239. public JavaUuidSessionIdGenerator getSessionIdGenerator() {
  240. JavaUuidSessionIdGenerator sessionIdGenerator = new JavaUuidSessionIdGenerator();
  241. return sessionIdGenerator;
  242. }
  243. /**
  244. * 缓存管理器 使用Ehcache实现
  245. *
  246. * @return
  247. */
  248. @Bean(name = "cacheShiroManager")
  249. public CacheManager getCacheShiroManage(EhCacheManagerFactoryBean ehCacheManagerFactoryBean) {
  250. EhCacheManager ehCacheManager = new EhCacheManager();
  251. // ehCacheManager.setCacheManagerConfigFile("classpath:ehcache-shiro.xml");
  252. ehCacheManager.setCacheManager(ehCacheManagerFactoryBean.getObject());
  253. return ehCacheManager;
  254. }
  255. /**
  256. * 会话Cookie模板
  257. *
  258. * @return
  259. */
  260. @Bean(name = "sessionIdCookie")
  261. public SimpleCookie getSessionIdCookie() {
  262. SimpleCookie cookie = new SimpleCookie("sid");
  263. cookie.setHttpOnly(true);
  264. cookie.setMaxAge(-1);
  265. return cookie;
  266. }
  267. /**
  268. * 会话验证调度器
  269. *
  270. * @return
  271. */
  272. @Bean(name = "sessionValidationScheduler")
  273. public ExecutorServiceSessionValidationScheduler getExecutorServiceSessionValidationScheduler() {
  274. ExecutorServiceSessionValidationScheduler scheduler = new ExecutorServiceSessionValidationScheduler();
  275. scheduler.setInterval(3600000);//每隔60分钟验证清理失效的session
  276. return scheduler;
  277. }
  278. /**
  279. * 相当于调用SecurityUtils.setSecurityManager(securityManager)
  280. *
  281. * @return
  282. */
  283. @Bean
  284. public MethodInvokingFactoryBean getMethodInvokingFactoryBean(EhCacheManagerFactoryBean ehCacheManagerFactoryBean) {
  285. MethodInvokingFactoryBean factoryBean = new MethodInvokingFactoryBean();
  286. factoryBean.setStaticMethod("org.apache.shiro.SecurityUtils.setSecurityManager");
  287. factoryBean.setArguments(new Object[]{getSecurityManager(ehCacheManagerFactoryBean)});
  288. return factoryBean;
  289. }
  290. /**
  291. * 开启Shiro的注解(如@RequiresRoles,@RequiresPermissions),需借助SpringAOP扫描使用Shiro注解的类,并在必要时进行安全逻辑验证
  292. * 配置以下两个bean即可实现此功能
  293. *
  294. * @return
  295. */
  296. @Bean
  297. @DependsOn("lifecycleBeanPostProcessor")
  298. public DefaultAdvisorAutoProxyCreator getAutoProxyCreator() {
  299. DefaultAdvisorAutoProxyCreator creator = new DefaultAdvisorAutoProxyCreator();
  300. creator.setProxyTargetClass(true);
  301. return creator;
  302. }
  303. @Bean
  304. public AuthorizationAttributeSourceAdvisor getAuthorizationAttributeSourceAdvisor(EhCacheManagerFactoryBean ehCacheManagerFactoryBean) {
  305. AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
  306. advisor.setSecurityManager(getSecurityManager(ehCacheManagerFactoryBean));
  307. return advisor;
  308. }
  309. /*
  310. * @methodName: loginFilter
  311. * @param: []
  312. * @description:登录过滤器
  313. * @return: com.jk.shiro.LoginFilter
  314. * @author: cuiP
  315. * @date: 2017/7/28 16:27
  316. * @version: V1.0.0
  317. */
  318. @Bean
  319. public LoginFilter loginFilter() {
  320. return new LoginFilter();
  321. }
  322. /**
  323. * ShiroDialect,为了在thymeleaf里使用shiro的标签的bean
  324. *
  325. * @return
  326. */
  327. @Bean
  328. public ShiroDialect shiroDialect() {
  329. return new ShiroDialect();
  330. }
  331. }