SpringSecurityConfig.java 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. /*
  2. * Copyright 2019-2020 Zheng Jie
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package me.zhengjie.security.config;
  17. import lombok.RequiredArgsConstructor;
  18. import me.zhengjie.annotation.AnonymousAccess;
  19. import me.zhengjie.security.config.bean.SecurityProperties;
  20. import me.zhengjie.security.security.TokenConfigurer;
  21. import me.zhengjie.security.security.TokenFilter;
  22. import me.zhengjie.security.security.TokenProvider;
  23. import me.zhengjie.security.service.OnlineUserService;
  24. import me.zhengjie.utils.enums.RequestMethodEnum;
  25. import org.springframework.context.ApplicationContext;
  26. import org.springframework.context.annotation.Bean;
  27. import org.springframework.context.annotation.Configuration;
  28. import org.springframework.http.HttpMethod;
  29. import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
  30. import org.springframework.security.config.annotation.web.builders.HttpSecurity;
  31. import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
  32. import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
  33. import org.springframework.security.config.core.GrantedAuthorityDefaults;
  34. import org.springframework.security.config.http.SessionCreationPolicy;
  35. import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
  36. import org.springframework.security.crypto.password.PasswordEncoder;
  37. import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
  38. import org.springframework.web.bind.annotation.RequestMethod;
  39. import org.springframework.web.filter.CorsFilter;
  40. import org.springframework.web.method.HandlerMethod;
  41. import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
  42. import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
  43. import java.util.*;
  44. /**
  45. * @author Zheng Jie
  46. */
  47. @Configuration
  48. @EnableWebSecurity
  49. @RequiredArgsConstructor
  50. @EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
  51. public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
  52. private final TokenProvider tokenProvider;
  53. private final CorsFilter corsFilter;
  54. // private final JwtAuthenticationEntryPoint authenticationErrorHandler;
  55. // private final JwtAccessDeniedHandler jwtAccessDeniedHandler;
  56. private final ApplicationContext applicationContext;
  57. private final SecurityProperties properties;
  58. private final OnlineUserService onlineUserService;
  59. @Bean
  60. GrantedAuthorityDefaults grantedAuthorityDefaults() {
  61. // 去除 ROLE_ 前缀
  62. return new GrantedAuthorityDefaults("");
  63. }
  64. @Bean
  65. public PasswordEncoder passwordEncoder() {
  66. // 密码加密方式
  67. return new BCryptPasswordEncoder();
  68. }
  69. @Override
  70. protected void configure(HttpSecurity httpSecurity) throws Exception {
  71. // 搜寻匿名标记 url: @AnonymousAccess
  72. RequestMappingHandlerMapping requestMappingHandlerMapping = (RequestMappingHandlerMapping) applicationContext.getBean("requestMappingHandlerMapping");
  73. Map<RequestMappingInfo, HandlerMethod> handlerMethodMap = requestMappingHandlerMapping.getHandlerMethods();
  74. // 获取匿名标记
  75. Map<String, Set<String>> anonymousUrls = getAnonymousUrl(handlerMethodMap);
  76. httpSecurity
  77. // 禁用 CSRF
  78. .csrf().disable()
  79. .addFilterBefore(corsFilter, UsernamePasswordAuthenticationFilter.class)
  80. // 授权异常
  81. .exceptionHandling()
  82. // .authenticationEntryPoint(authenticationErrorHandler)
  83. // .accessDeniedHandler(jwtAccessDeniedHandler)
  84. // 防止iframe 造成跨域
  85. .and()
  86. .headers()
  87. .frameOptions()
  88. .disable()
  89. // 不创建会话
  90. .and()
  91. .sessionManagement()
  92. .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
  93. .and()
  94. .authorizeRequests()
  95. // 静态资源等等
  96. .antMatchers(
  97. HttpMethod.GET,
  98. "/*.html",
  99. "/**/*.html",
  100. "/**/*.png",
  101. "/**/*.css",
  102. "/**/*.ico",
  103. "/**/*.js",
  104. "/webSocket/**",
  105. "/appSocketServer/**",
  106. "/socket.io/**"
  107. // "/tencentpush",
  108. // "/apppush"
  109. ).permitAll()
  110. // swagger 文档
  111. .antMatchers("/swagger-ui.html").permitAll()
  112. .antMatchers("/swagger-resources/**").permitAll()
  113. .antMatchers("/app/**").permitAll()
  114. .antMatchers("/api/bank-app/**").permitAll()
  115. .antMatchers("/minipro/**").permitAll()
  116. .antMatchers("/image/**").permitAll()
  117. .antMatchers("/webjars/**").permitAll()
  118. .antMatchers("/*/api-docs").permitAll()
  119. // 文件
  120. .antMatchers("/avatar/**").permitAll()
  121. .antMatchers("/file/**").permitAll()
  122. .antMatchers("/static/**").permitAll()
  123. // 阿里巴巴 druid
  124. .antMatchers("/druid/**").permitAll()
  125. // 放行OPTIONS请求
  126. .antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
  127. // 自定义匿名访问所有url放行:允许匿名和带Token访问,细腻化到每个 Request 类型
  128. // GET
  129. .antMatchers(HttpMethod.GET, anonymousUrls.get(RequestMethodEnum.GET.getType()).toArray(new String[0])).permitAll()
  130. // POST
  131. .antMatchers(HttpMethod.POST, anonymousUrls.get(RequestMethodEnum.POST.getType()).toArray(new String[0])).permitAll()
  132. // PUT
  133. .antMatchers(HttpMethod.PUT, anonymousUrls.get(RequestMethodEnum.PUT.getType()).toArray(new String[0])).permitAll()
  134. // PATCH
  135. .antMatchers(HttpMethod.PATCH, anonymousUrls.get(RequestMethodEnum.PATCH.getType()).toArray(new String[0])).permitAll()
  136. // DELETE
  137. .antMatchers(HttpMethod.DELETE, anonymousUrls.get(RequestMethodEnum.DELETE.getType()).toArray(new String[0])).permitAll()
  138. // 所有类型的接口都放行
  139. .antMatchers(anonymousUrls.get(RequestMethodEnum.ALL.getType()).toArray(new String[0])).permitAll()
  140. // 所有请求都需要认证
  141. .anyRequest().authenticated()
  142. .and().apply(securityConfigurerAdapter());
  143. //设置所有的不需要权限访问的
  144. TokenFilter.setAnonymousUrl(anonymousUrls);
  145. System.out.println(anonymousUrls);
  146. }
  147. private TokenConfigurer securityConfigurerAdapter() {
  148. return new TokenConfigurer(tokenProvider, properties, onlineUserService);
  149. }
  150. private Map<String, Set<String>> getAnonymousUrl(Map<RequestMappingInfo, HandlerMethod> handlerMethodMap) {
  151. Map<String, Set<String>> anonymousUrls = new HashMap<>(8);
  152. Set<String> get = new HashSet<>();
  153. Set<String> post = new HashSet<>();
  154. Set<String> put = new HashSet<>();
  155. Set<String> patch = new HashSet<>();
  156. Set<String> delete = new HashSet<>();
  157. Set<String> all = new HashSet<>();
  158. for (Map.Entry<RequestMappingInfo, HandlerMethod> infoEntry : handlerMethodMap.entrySet()) {
  159. HandlerMethod handlerMethod = infoEntry.getValue();
  160. AnonymousAccess anonymousAccess = handlerMethod.getMethodAnnotation(AnonymousAccess.class);
  161. if (null != anonymousAccess) {
  162. List<RequestMethod> requestMethods = new ArrayList<>(infoEntry.getKey().getMethodsCondition().getMethods());
  163. RequestMethodEnum request = RequestMethodEnum.find(requestMethods.size() == 0 ? RequestMethodEnum.ALL.getType() : requestMethods.get(0).name());
  164. switch (Objects.requireNonNull(request)) {
  165. case GET:
  166. get.addAll(infoEntry.getKey().getPatternsCondition().getPatterns());
  167. break;
  168. case POST:
  169. post.addAll(infoEntry.getKey().getPatternsCondition().getPatterns());
  170. break;
  171. case PUT:
  172. put.addAll(infoEntry.getKey().getPatternsCondition().getPatterns());
  173. break;
  174. case PATCH:
  175. patch.addAll(infoEntry.getKey().getPatternsCondition().getPatterns());
  176. break;
  177. case DELETE:
  178. delete.addAll(infoEntry.getKey().getPatternsCondition().getPatterns());
  179. break;
  180. default:
  181. all.addAll(infoEntry.getKey().getPatternsCondition().getPatterns());
  182. break;
  183. }
  184. }
  185. }
  186. anonymousUrls.put(RequestMethodEnum.GET.getType(), get);
  187. anonymousUrls.put(RequestMethodEnum.POST.getType(), post);
  188. anonymousUrls.put(RequestMethodEnum.PUT.getType(), put);
  189. anonymousUrls.put(RequestMethodEnum.PATCH.getType(), patch);
  190. anonymousUrls.put(RequestMethodEnum.DELETE.getType(), delete);
  191. anonymousUrls.put(RequestMethodEnum.ALL.getType(), all);
  192. return anonymousUrls;
  193. }
  194. }