跨域问题之Spring的跨域的方案

简介: 跨域问题之Spring的跨域的方案

Spring的跨域的方案

@CrossOrigin

@CrossOrigin可以添加到方法上,也可以添加到Controller上

AbstractHandlerMethodMapping的内部类MappingRegistry的register:

public void register(T mapping, Object handler, Method method) {
   // Assert that the handler method is not a suspending one.
   if (KotlinDetector.isKotlinType(method.getDeclaringClass())) {
      Class<?>[] parameterTypes = method.getParameterTypes();
      if ((parameterTypes.length > 0) && "kotlin.coroutines.Continuation".equals(parameterTypes[parameterTypes.length - 1].getName())) {
         throw new IllegalStateException("Unsupported suspending handler method detected: " + method);
      }
   }
   this.readWriteLock.writeLock().lock();
   try {
      HandlerMethod handlerMethod = createHandlerMethod(handler, method);
      validateMethodMapping(handlerMethod, mapping);
      this.mappingLookup.put(mapping, handlerMethod);

      List<String> directUrls = getDirectUrls(mapping);
      for (String url : directUrls) {
         this.urlLookup.add(url, mapping);
      }

      String name = null;
      if (getNamingStrategy() != null) {
         name = getNamingStrategy().getName(handlerMethod, mapping);
         addMappingName(name, handlerMethod);
      }

      CorsConfiguration corsConfig = initCorsConfiguration(handler, method, mapping);
      if (corsConfig != null) {
         this.corsLookup.put(handlerMethod, corsConfig);
      }

      this.registry.put(mapping, new MappingRegistration<>(mapping, handlerMethod, directUrls, name));
   }
   finally {
      this.readWriteLock.writeLock().unlock();
   }
}
  1. @CrossOrigin 注解在AbstractHandlerMethodMapping的内部类MappingRegistry的register方法中完成解析,@CrossOrigin注解中的内容会被解析成一个配置对象CorsConfiguration
  2. 将@CrossOrigin所标记的请求方法对象HandlerMethod和CorsConfiguration一一对应存入corsLookup的map集合中
  3. 当请求到达DispatcherServlet的doDispatch方法之后,调用AbstractHandlerMapping的getHandler方法获取执行链HandlerExecutionChain时,会从map中获取CorsConfiguration对象
  4. 根据获取到的CorsConfiguration对象构建一个CorsInterceptor拦截器
  5. 在CorsInterceptor拦截器中触发对CorsProcessor的processRequest方法调用,跨域请求的校验工作将在该方法中完成。

addCorsMappings

@CrossOrigin是添加在不同的Controller中 全局配置

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedMethods("*")
                .allowedOrigins("*")
                .allowedHeaders("*")
                .allowCredentials(false)
                .exposedHeaders("")
                .maxAge(3600);
    }
}

全局配置和@CrossOrigin注解相同,都是在CorsInterceptor拦截器中触发对CorsProcessor的processRequest方法调用,最终在该方法中完成跨域请求的校验工作

  1. registry.addMapping("/**")方法中配置了一个CorsRegistration对象,该对象中包含了一个路径拦截规则,同时CorsRegistration还包含了一个CorsConfiguration配置对象,该对象用来保存这里跨域相关的配置。
  2. 在WebMvcConfigurationSupport的requestMappingHandlerMapping方法中触发了addCorsMappings方法执行,将获取到的CorsRegistration对象重新组装成一个UrlBasedCorsConfigurationSource对象,该对象保存了拦截规则和CorsConfiguration对象的映射关系。
  3. 将新建的UrlBasedCorsConfigurationSource对象赋值给AbstractHandlerMapping的corsConfigurationSource属性
  4. 当请求到达时的处理方法和@CrossOrigin注解处理流程一样,在AbstractHandlerMapping的getHandler方法处理,从corsConfigurationSource中获取CorsConfiguration配置对象,而@CrossOrigin从map中获取CorsConfiguration对象。如果两处都可以获取到CorsConfiguration对象,则获取到的对象属性值进行合并。
  5. 根据获取到的CorsConfiguration对象构造CorsInterceptor拦截器
  6. 在CorsInterceptor拦截器中触发对CorsProcessor的processRequest方法调用,跨域请求的校验工作将在该方法中完成。

这里的跨域校验是通过DispatcherServlet中的方法触发的,DispatcherServlet在Filter之后执行

CorsFIlter

@Configuration
public class WebMvcConfig {
    @Bean
    FilterRegistrationBean<CorsFilter> corsFilter() {
        FilterRegistrationBean<CorsFilter> registrationBean = new FilterRegistrationBean<>();
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.setAllowedHeaders(Arrays.asList("*"));
        corsConfiguration.setAllowedMethods(Arrays.asList("*"));
        corsConfiguration.setAllowedOrigins(Arrays.asList("http://localhost:8081"));
        corsConfiguration.setMaxAge(3600L);
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", corsConfiguration);
        registrationBean.setFilter(new CorsFilter(source));
        registrationBean.setOrder(-1);
        return registrationBean;
    }
}
  1. 手动创建CorsConfiguration对象
  2. 创建UrlBasedCorsConfigurationSource对象,将过滤器的拦截规则和CorsConfiguration对象之间的映射关系由UrlBasedCorsConfigurationSource中的corsConfiguration变量保存起来。
  3. 最后创建CorsFilter 设置优先级

CorsFilter的doFilterInternal方法:

protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
    CorsConfiguration corsConfiguration = this.configSource.getCorsConfiguration(request);
    boolean isValid = this.processor.processRequest(corsConfiguration, request, response);
    if (isValid && !CorsUtils.isPreFlightRequest(request)) {
        filterChain.doFilter(request, response);
    }
}

触发对CorsProcessor的processRequest方法调用,跨域请求的校验工作将在该方法中完成

相关文章
|
6天前
|
人工智能 JSON 前端开发
Spring Boot解决跨域问题方法汇总
Spring Boot解决跨域问题方法汇总
|
6天前
|
安全 Java 数据安全/隐私保护
|
6天前
|
缓存 前端开发 Java
13:SpringBoot跨域解决方案-Java Spring
13:SpringBoot跨域解决方案-Java Spring
90 0
|
1天前
|
JSON 安全 前端开发
跨域详解及Spring Boot 3中的跨域解决方案
本文介绍了Web开发中的跨域问题,包括概念、原因、影响以及在Spring Boot 3中的解决方案。跨域是由浏览器的同源策略限制引起的,阻碍了不同源之间的数据传输。解决方法包括CORS、JSONP和代理服务器。在Spring Boot 3中,可以通过配置CorsFilter来允许跨域请求,实现前后端分离项目的正常运行。
51 3
 跨域详解及Spring Boot 3中的跨域解决方案
|
6天前
|
Java Spring
快速解决Spring Boot跨域困扰:使用CORS实现无缝跨域支持
这是一个简单的配置示例,用于在Spring Boot应用程序中实现CORS支持。根据你的项目需求,你可能需要更详细的配置来限制允许的来源、方法和标头。
29 3
|
6月前
|
Java 测试技术 数据安全/隐私保护
Spring Boot | 一种优雅的参数校验方案(个人总结)
一种优雅的参数校验方案(个人总结)
349 1
Spring Boot | 一种优雅的参数校验方案(个人总结)
|
6天前
|
安全 前端开发 JavaScript
spring boot3解决跨域的几种方式
spring boot3解决跨域的几种方式
80 3
|
6天前
|
Java
【Java专题_03】spring-boot跨域问题如何解决
【Java专题_03】spring-boot跨域问题如何解决
28 0
|
6天前
|
存储 算法 Java
Spring Boot 通用限流方案
Spring Boot 通用限流方案
151 0
|
6天前
|
Java Spring
spring boot 跨域问题
spring boot 跨域问题
26 0