ShiroConfig.java 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. package org.king.config;
  2. import cn.hutool.core.util.StrUtil;
  3. import lombok.extern.slf4j.Slf4j;
  4. import org.apache.shiro.mgt.DefaultSessionStorageEvaluator;
  5. import org.apache.shiro.mgt.DefaultSubjectDAO;
  6. import org.apache.shiro.mgt.SecurityManager;
  7. import org.apache.shiro.spring.LifecycleBeanPostProcessor;
  8. import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
  9. import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
  10. import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
  11. import org.crazycake.shiro.IRedisManager;
  12. import org.crazycake.shiro.RedisCacheManager;
  13. import org.crazycake.shiro.RedisClusterManager;
  14. import org.crazycake.shiro.RedisManager;
  15. import org.king.modules.shiro.authc.ShiroRealm;
  16. import org.king.modules.shiro.authc.aop.JwtFilter;
  17. import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
  18. import org.springframework.beans.factory.annotation.Value;
  19. import org.springframework.context.annotation.Bean;
  20. import org.springframework.context.annotation.Configuration;
  21. import org.springframework.context.annotation.DependsOn;
  22. import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
  23. import redis.clients.jedis.HostAndPort;
  24. import redis.clients.jedis.JedisCluster;
  25. import javax.annotation.Resource;
  26. import javax.servlet.Filter;
  27. import java.util.HashMap;
  28. import java.util.HashSet;
  29. import java.util.LinkedHashMap;
  30. import java.util.Map;
  31. import java.util.Set;
  32. /**
  33. * @author: Scott
  34. * @date: 2018/2/7
  35. * @description: shiro 配置类
  36. */
  37. @Slf4j
  38. @Configuration
  39. public class ShiroConfig {
  40. @Value("${king.shiro.excludeUrls}")
  41. private String excludeUrls;
  42. @Resource
  43. LettuceConnectionFactory lettuceConnectionFactory;
  44. /**
  45. * Filter Chain定义说明
  46. *
  47. * 1、一个URL可以配置多个Filter,使用逗号分隔
  48. * 2、当设置多个过滤器时,全部验证通过,才视为通过
  49. * 3、部分过滤器可指定参数,如perms,roles
  50. */
  51. @Bean("shiroFilter")
  52. public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
  53. ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
  54. shiroFilterFactoryBean.setSecurityManager(securityManager);
  55. // 拦截器
  56. Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
  57. if(StrUtil.isNotBlank(excludeUrls)){
  58. String[] permissionUrl = excludeUrls.split(",");
  59. for(String url : permissionUrl){
  60. filterChainDefinitionMap.put(url,"anon");
  61. }
  62. }
  63. //cas验证登录
  64. filterChainDefinitionMap.put("/cas/client/validateLogin", "anon");
  65. // 配置不会被拦截的链接 顺序判断
  66. filterChainDefinitionMap.put("/sys/randomImage/**", "anon"); //登录验证码接口排除
  67. filterChainDefinitionMap.put("/sys/checkCaptcha", "anon"); //登录验证码接口排除
  68. filterChainDefinitionMap.put("/sys/login", "anon"); //登录接口排除
  69. filterChainDefinitionMap.put("/sys/mLogin", "anon"); //登录接口排除
  70. filterChainDefinitionMap.put("/sys/logout", "anon"); //登出接口排除
  71. filterChainDefinitionMap.put("/thirdLogin/**", "anon"); //第三方登录
  72. filterChainDefinitionMap.put("/sys/getEncryptedString", "anon"); //获取加密串
  73. filterChainDefinitionMap.put("/sys/sms", "anon");//短信验证码
  74. filterChainDefinitionMap.put("/sys/phoneLogin", "anon");//手机登录
  75. filterChainDefinitionMap.put("/sys/user/checkOnlyUser", "anon");//校验用户是否存在
  76. filterChainDefinitionMap.put("/sys/user/register", "anon");//用户注册
  77. filterChainDefinitionMap.put("/sys/user/querySysUser", "anon");//根据手机号获取用户信息
  78. filterChainDefinitionMap.put("/sys/user/phoneVerification", "anon");//用户忘记密码验证手机号
  79. filterChainDefinitionMap.put("/sys/user/passwordChange", "anon");//用户更改密码
  80. filterChainDefinitionMap.put("/auth/2step-code", "anon");//登录验证码
  81. filterChainDefinitionMap.put("/sys/common/pdf/**", "anon");//pdf预览
  82. filterChainDefinitionMap.put("/generic/**", "anon");//pdf预览需要文件
  83. filterChainDefinitionMap.put("/", "anon");
  84. filterChainDefinitionMap.put("/doc.html", "anon");
  85. filterChainDefinitionMap.put("/**/*.js", "anon");
  86. filterChainDefinitionMap.put("/**/*.css", "anon");
  87. filterChainDefinitionMap.put("/**/*.html", "anon");
  88. filterChainDefinitionMap.put("/**/*.svg", "anon");
  89. filterChainDefinitionMap.put("/**/*.pdf", "anon");
  90. filterChainDefinitionMap.put("/**/*.jpg", "anon");
  91. filterChainDefinitionMap.put("/**/*.png", "anon");
  92. filterChainDefinitionMap.put("/**/*.ico", "anon");
  93. filterChainDefinitionMap.put("/staticalCount/**", "anon"); //登录验证码接口排除
  94. // update-begin--Author:sunjianlei Date:20190813 for:排除字体格式的后缀
  95. filterChainDefinitionMap.put("/**/*.ttf", "anon");
  96. filterChainDefinitionMap.put("/**/*.woff", "anon");
  97. filterChainDefinitionMap.put("/**/*.woff2", "anon");
  98. // update-begin--Author:sunjianlei Date:20190813 for:排除字体格式的后缀
  99. filterChainDefinitionMap.put("/druid/**", "anon");
  100. filterChainDefinitionMap.put("/swagger-ui.html", "anon");
  101. filterChainDefinitionMap.put("/swagger**/**", "anon");
  102. filterChainDefinitionMap.put("/webjars/**", "anon");
  103. filterChainDefinitionMap.put("/v2/**", "anon");
  104. //性能监控
  105. filterChainDefinitionMap.put("/actuator/metrics/**", "anon");
  106. filterChainDefinitionMap.put("/actuator/httptrace/**", "anon");
  107. filterChainDefinitionMap.put("/actuator/redis/**", "anon");
  108. //websocket排除
  109. filterChainDefinitionMap.put("/websocket/**", "anon");
  110. filterChainDefinitionMap.put("/newsWebsocket/**", "anon");
  111. //测试示例
  112. filterChainDefinitionMap.put("/big/screen/**", "anon");
  113. filterChainDefinitionMap.put("/bigscreen/**", "anon");
  114. //排除Online请求
  115. filterChainDefinitionMap.put("/auto/cgform/**", "anon");
  116. //排除微信相关不需登录的请求
  117. filterChainDefinitionMap.put("/wx/portal/**", "anon");
  118. filterChainDefinitionMap.put("/wx/**/authorize", "anon");
  119. filterChainDefinitionMap.put("/wx/**/getUserInfoByCode", "anon");
  120. filterChainDefinitionMap.put("/wx/**/jsapiSignature", "anon");
  121. filterChainDefinitionMap.put("/wx/**/sessionToMpUserTest", "anon");
  122. filterChainDefinitionMap.put("/wxPay/notify/order", "anon");
  123. filterChainDefinitionMap.put("/ma/portal/**", "anon");
  124. filterChainDefinitionMap.put("/ma/user/**", "anon");
  125. filterChainDefinitionMap.put("/cp/portal/**", "anon");
  126. // 添加自己的过滤器并且取名为jwt
  127. Map<String, Filter> filterMap = new HashMap< >(1);
  128. filterMap.put("jwt", new JwtFilter());
  129. shiroFilterFactoryBean.setFilters(filterMap);
  130. // <!-- 过滤链定义,从上向下顺序执行,一般将/**放在最为下边
  131. filterChainDefinitionMap.put("/**", "jwt");
  132. // 未授权界面返回JSON
  133. shiroFilterFactoryBean.setUnauthorizedUrl("/sys/common/403");
  134. shiroFilterFactoryBean.setLoginUrl("/sys/common/403");
  135. shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
  136. return shiroFilterFactoryBean;
  137. }
  138. @Bean("securityManager")
  139. public DefaultWebSecurityManager securityManager(ShiroRealm myRealm) {
  140. DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
  141. securityManager.setRealm(myRealm);
  142. /*
  143. * 关闭shiro自带的session,详情见文档
  144. * http://shiro.apache.org/session-management.html#SessionManagement-
  145. * StatelessApplications%28Sessionless%29
  146. */
  147. DefaultSubjectDAO subjectDAO = new DefaultSubjectDAO();
  148. DefaultSessionStorageEvaluator defaultSessionStorageEvaluator = new DefaultSessionStorageEvaluator();
  149. defaultSessionStorageEvaluator.setSessionStorageEnabled(false);
  150. subjectDAO.setSessionStorageEvaluator(defaultSessionStorageEvaluator);
  151. securityManager.setSubjectDAO(subjectDAO);
  152. //自定义缓存实现,使用redis
  153. securityManager.setCacheManager(redisCacheManager());
  154. return securityManager;
  155. }
  156. /**
  157. * 下面的代码是添加注解支持
  158. * @return
  159. */
  160. @Bean
  161. @DependsOn("lifecycleBeanPostProcessor")
  162. public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
  163. DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
  164. defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);
  165. /**
  166. * 解决重复代理问题
  167. * 添加前缀判断 不匹配 任何Advisor
  168. */
  169. defaultAdvisorAutoProxyCreator.setUsePrefix(true);
  170. defaultAdvisorAutoProxyCreator.setAdvisorBeanNamePrefix("_no_advisor");
  171. return defaultAdvisorAutoProxyCreator;
  172. }
  173. @Bean
  174. public static LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
  175. return new LifecycleBeanPostProcessor();
  176. }
  177. @Bean
  178. public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager) {
  179. AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
  180. advisor.setSecurityManager(securityManager);
  181. return advisor;
  182. }
  183. /**
  184. * cacheManager 缓存 redis实现
  185. * 使用的是shiro-redis开源插件
  186. *
  187. * @return
  188. */
  189. public RedisCacheManager redisCacheManager() {
  190. log.info("===============(1)创建缓存管理器RedisCacheManager");
  191. RedisCacheManager redisCacheManager = new RedisCacheManager();
  192. redisCacheManager.setRedisManager(redisManager());
  193. //redis中针对不同用户缓存(此处的id需要对应user实体中的id字段,用于唯一标识)
  194. redisCacheManager.setPrincipalIdFieldName("id");
  195. //用户权限信息缓存时间
  196. redisCacheManager.setExpire(200000);
  197. return redisCacheManager;
  198. }
  199. /**
  200. * 配置shiro redisManager
  201. * 使用的是shiro-redis开源插件
  202. *
  203. * @return
  204. */
  205. @Bean
  206. public IRedisManager redisManager() {
  207. log.info("===============(2)创建RedisManager,连接Redis..");
  208. IRedisManager manager;
  209. // redis 单机支持,在集群为空,或者集群无机器时候使用 add by jzyadmin@163.com
  210. if (lettuceConnectionFactory.getClusterConfiguration() == null || lettuceConnectionFactory.getClusterConfiguration().getClusterNodes().isEmpty()) {
  211. RedisManager redisManager = new RedisManager();
  212. redisManager.setHost(lettuceConnectionFactory.getHostName());
  213. redisManager.setPort(lettuceConnectionFactory.getPort());
  214. redisManager.setTimeout(0);
  215. if (!StrUtil.isEmpty(lettuceConnectionFactory.getPassword())) {
  216. redisManager.setPassword(lettuceConnectionFactory.getPassword());
  217. }
  218. manager = redisManager;
  219. }else{
  220. // redis 集群支持,优先使用集群配置 add by jzyadmin@163.com
  221. RedisClusterManager redisManager = new RedisClusterManager();
  222. Set<HostAndPort> portSet = new HashSet<>();
  223. lettuceConnectionFactory.getClusterConfiguration().getClusterNodes().forEach(node -> portSet.add(new HostAndPort(node.getHost() , node.getPort())));
  224. JedisCluster jedisCluster = new JedisCluster(portSet);
  225. redisManager.setJedisCluster(jedisCluster);
  226. manager = redisManager;
  227. }
  228. return manager;
  229. }
  230. }