SpringSecurity5(11-跨域配置)

打印 上一主题 下一主题

主题 1830|帖子 1830|积分 5490

SpringBoot跨域处理

@CrossOrigin(局部跨域)


  • 作用在方法上
  1. @RestController
  2. public class IndexController {
  3.     @CrossOrigin(value = "http://localhost:8082")
  4.     @GetMapping("/hello")
  5.     public String hello() {
  6.         return "get hello";
  7.     }
  8.     @CrossOrigin(value = "http://localhost:8082")
  9.     @PostMapping("/hello")
  10.     public String hello2() {
  11.         return "post hello";
  12.     }
  13. }
复制代码

  • 作用在类上
  1. @CrossOrigin(origins = "http://example.com", maxAge = 3600)
  2. @RestController
  3. @RequestMapping("/account")
  4. public class AccountController {
  5.     @RequestMapping(method = RequestMethod.GET, path = "/{id}")
  6.     public Account retrieve(@PathVariable Long id) {
  7.         // ...
  8.     }
  9.     @RequestMapping(method = RequestMethod.DELETE, path = "/{id}")
  10.     public void remove(@PathVariable Long id) {
  11.         // ...
  12.     }
  13. }
复制代码
WebMvcConfigurer(全局跨域)
  1. @Configuration
  2. public class WebMvcConfig implements WebMvcConfigurer {
  3.     @Override
  4.     public void addCorsMappings(CorsRegistry registry) {
  5.         registry.addMapping("/**")
  6.                 .allowedHeaders("Content-Type","X-Requested-With","accept,Origin","Access-Control-Request-Method","Access-Control-Request-Headers","token")
  7.                 .allowedMethods("*")
  8.                 .allowedOrigins("*")
  9.                 .allowCredentials(true);
  10.     }
  11. }
复制代码
SpringSecurity跨域处理

跨域配置详解

如果利用了 Spring Security,上面的跨域配置会失效,因为请求被 Spring Security 拦截了
在项目中利用 Spring Security,我们必须采取额外的步骤确保它与 CORS 协作精良。这是因为 CORS 需要首先处理,否则,Spring Security 会在请求到达 Spring MVC 之前将其拒绝
  1. @Configuration
  2. public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
  3.     @Override
  4.     protected void configure(HttpSecurity http) throws Exception {
  5.         http.cors().and()...
  6.     }
  7. }
复制代码
可以配置 CORS 以覆盖默认的 Spring Security CORS 处理器。为此,我们需要添加一个 CorsConfigurationSource Bean,利用 CorsConfiguration 实例来处理 CORS 配置。如果添加了 CorsFilter Bean,http.cors() 方法就会利用 CorsFilter,否则就会利用 CorsConfigurationSource。如果两者都未配置,则利用 Spring MVC pattern inspector handler。
  1. public class CorsConfigurer<H extends HttpSecurityBuilder<H>>
  2.                 extends AbstractHttpConfigurer<CorsConfigurer<H>, H> {
  3.     private static final String HANDLER_MAPPING_INTROSPECTOR = "org.springframework.web.servlet.handler.HandlerMappingIntrospector";
  4.     private static final String CORS_CONFIGURATION_SOURCE_BEAN_NAME = "corsConfigurationSource";
  5.     private static final String CORS_FILTER_BEAN_NAME = "corsFilter";
  6.     private CorsConfigurationSource configurationSource;
  7.     public CorsConfigurer() {
  8.     }
  9.     public CorsConfigurer<H> configurationSource(
  10.             CorsConfigurationSource configurationSource) {
  11.         this.configurationSource = configurationSource;
  12.         return this;
  13.     }
  14.     @Override
  15.     public void configure(H http) {
  16.         ApplicationContext context = http.getSharedObject(ApplicationContext.class);
  17.         CorsFilter corsFilter = getCorsFilter(context);
  18.         if (corsFilter == null) {
  19.             throw new IllegalStateException(
  20.                     "Please configure either a " + CORS_FILTER_BEAN_NAME + " bean or a "
  21.                             + CORS_CONFIGURATION_SOURCE_BEAN_NAME + "bean.");
  22.         }
  23.         http.addFilter(corsFilter);
  24.     }
  25.     private CorsFilter getCorsFilter(ApplicationContext context) {
  26.         if (this.configurationSource != null) {
  27.             return new CorsFilter(this.configurationSource);
  28.         }
  29.         // 查找是否有名为corsFilter的Bean对象
  30.         boolean containsCorsFilter = context
  31.                 .containsBeanDefinition(CORS_FILTER_BEAN_NAME);
  32.         if (containsCorsFilter) {
  33.             return context.getBean(CORS_FILTER_BEAN_NAME, CorsFilter.class);
  34.         }
  35.         // 查找是否有名为corsConfigurationSource的Bean对象
  36.         boolean containsCorsSource = context
  37.                 .containsBean(CORS_CONFIGURATION_SOURCE_BEAN_NAME);
  38.         if (containsCorsSource) {
  39.             CorsConfigurationSource configurationSource = context.getBean(
  40.                     CORS_CONFIGURATION_SOURCE_BEAN_NAME, CorsConfigurationSource.class);
  41.             return new CorsFilter(configurationSource);
  42.         }
  43.         // 查找是否有org.springframework.web.servlet.handler.HandlerMappingIntrospector该类
  44.         boolean mvcPresent = ClassUtils.isPresent(HANDLER_MAPPING_INTROSPECTOR,
  45.                 context.getClassLoader());
  46.         if (mvcPresent) {
  47.             return MvcCorsFilter.getMvcCorsFilter(context);
  48.         }
  49.         return null;
  50.     }
  51.     static class MvcCorsFilter {
  52.         private static final String HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME = "mvcHandlerMappingIntrospector";
  53.         private static CorsFilter getMvcCorsFilter(ApplicationContext context) {
  54.             if (!context.containsBean(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME)) {
  55.                 throw new NoSuchBeanDefinitionException(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME, "A Bean named " + HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME +" of type " + HandlerMappingIntrospector.class.getName()
  56.                         + " is required to use MvcRequestMatcher. Please ensure Spring Security & Spring MVC are configured in a shared ApplicationContext.");
  57.             }
  58.             // 获取名为mvcHandlerMappingIntrospector的Bean对象
  59.             HandlerMappingIntrospector mappingIntrospector = context.getBean(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME, HandlerMappingIntrospector.class);
  60.             return new CorsFilter(mappingIntrospector);
  61.         }
  62.     }
  63. }
复制代码
CorsConfigurationSource(全局跨域)
  1. @Configuration
  2. public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
  3.     @Override
  4.     protected void configure(HttpSecurity http) throws Exception {
  5.         http.authorizeRequests()
  6.             .anyRequest()
  7.             .permitAll()
  8.             .and()
  9.             .formLogin()
  10.             .permitAll()
  11.             .and()
  12.             .httpBasic()
  13.             .and()
  14.             // 支持跨域访问
  15.             .cors()
  16.             // 可以选择配置
  17.             //.configurationSource(corsConfigurationSource())
  18.             .and()
  19.             .csrf()
  20.             .disable();
  21.     }
  22.    
  23.     @Bean
  24.     public CorsConfigurationSource corsConfigurationSource() {
  25.         CorsConfiguration configuration = new CorsConfiguration();
  26.         configuration.setAllowedOrigins(Arrays.asList("*"));
  27.         configuration.setAllowedMethods(Arrays.asList("*"));
  28.         configuration.setAllowedHeaders(Arrays.asList("*"));
  29.         UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
  30.         source.registerCorsConfiguration("/**", configuration);
  31.         return source;
  32.     }
  33. }
复制代码
CosFilter(全局跨域)

还有一种情况就是支持 OAuth2 相关接口的跨域,比如用户要访问 OAuth2 中的 /oauth/token 等接口,可以配置一个全局的 CorsFilter 跨域过滤器类
  1. @Configuration
  2. public class GlobalCorsConfig {
  3.    
  4.     @Bean
  5.     public CorsFilter corsFilter() {
  6.         //1.添加CORS配置信息
  7.         CorsConfiguration config = new CorsConfiguration();
  8.         //放行哪些原始域
  9.         config.addAllowedOrigin("*");
  10.         //是否发送Cookie信息
  11.         config.setAllowCredentials(true);
  12.         //放行哪些原始域(请求方式)
  13.         config.addAllowedMethod("*");
  14.         //放行哪些原始域(头部信息)
  15.         config.addAllowedHeader("*");
  16.         //暴露哪些头部信息(因为跨域访问默认不能获取全部头部信息)
  17.         config.addExposedHeader("*");
  18.         //2.添加映射路径
  19.         UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource();
  20.         configSource.registerCorsConfiguration("/**", config);
  21.         //3.返回新的CorsFilter.
  22.         return new CorsFilter(configSource);
  23.     }
  24. }
复制代码
自定义Filter(全局跨域)
  1. public class CorsFilter extends OncePerRequestFilter {
  2.    
  3.     @Override
  4.     protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
  5.         String orignalHeader = StringUtils.defaultIfBlank(request.getHeader("Origin"), "*");
  6.         // 指定本次预检请求的有效期
  7.         response.setHeader("Access-Control-Max-Age", "3600");
  8.         // 服务器支持的所有头信息字段
  9.         response.setHeader("Access-Control-Allow-Headers", request.getHeader("Access-Control-Request-Headers"));
  10.         response.setHeader("Access-Control-Allow-Origin", orignalHeader);
  11.         response.setHeader("Access-Control-Allow-Credentials", "true");
  12.         response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT");
  13.         filterChain.doFilter(request, response);
  14.     }
  15. }
复制代码
  1. @Configuration
  2. public class WebMvcConfig extends WebSecurityConfigurerAdapter {
  3.    
  4.     @Override
  5.     public void configure(HttpSecurity http) throws Exception {
  6.         http.addFilterBefore(new CorsFilter(), WebAsyncManagerIntegrationFilter.class);
  7.     }
  8. }
复制代码


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

北冰洋以北

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表