CORS跨域资源共享(二):详解Spring MVC对CORS支持的相关类和API【享学Spring MVC】(上)

简介: CORS跨域资源共享(二):详解Spring MVC对CORS支持的相关类和API【享学Spring MVC】(上)

前言


上篇文章通过我模拟的跨域请求实例和结果分析,相信小伙伴们都已经80%的掌握了CORS到底是怎么一回事以及如何使用它。由于Java语言中的web框架几乎都是使用的Spring MVC,因此本文将聚焦于Spring MVC对CORS的支持,深度分析下它对CORS支持的相关API,这也方便下一章节的灵活使用以及流程原理分析。


Spring MVC与CORS


Spring MVC一直到4.2版本“才”开始内置对CORS支持,至于为何到这个版本Spring官方才对此提供支持,我这里需要结合时间轴来给大家解释一下。

上文我有说到了CORS它属于W3C的标准。我们知道任何一个规范的形成都是非常漫长的。W3C对web标准的制定分为如下7个阶段(从上到下有序):


  1. WD(Working Draft 工作草案):不稳定也不完整
  2. CR(Candidate Recommendation 候选推荐标准):所有的已知issues都被解决了
  3. PR(Proposed Recommendation 提案推荐标准):在浏览器做各种测试,此部分不会再有实质性的改动
  4. PER(Proposed Edited Recommendation 已修订的提案推荐标准):
  5. REC(Recommendation 推荐标准,通常称之为 standard,即事实标准):几乎不会再变动任何东西
  6. RET(Retired 退役的):最后这两个是建立在REC基础上变来,成熟的技术一般都不会有后面这两个
  7. NOTE(Group Note 工作组说明):


关于这7步,从这里 可以看倒CORS的WD从2009-03-17开始,2014-01-16进入的REC阶段,可谓正式毕业。而Spring4.2是在2015-06发布给与的全面支持,从时间轴上看Spring的响应速度还是把握得不错的(毕竟CORS经历过一段时间市场的考验Spring才敢全面纳入进来支持嘛~)


Tips:在Spring4.2之前,官方没有提供内置的支持,所以那时都是自己使用Filter/拦截器来处理。它的唯一缺点就是可能没那么灵活和优雅,后续官方提供标注支持后能力更强更为灵活了(底层原理都一样)


Spring MVC中CORS相关类及API说明


所有涉及到和CORS相关的类、注解、代码片段都是Spring4.2后才有的,请保持一定的版本意识。


image.png


从截图里可以看出spring-web包提供的专门用于处理CORS的相关的类,下面有必要进行逐个分析

CorsConfiguration


它代表一个cors配置,记录着各种配置项。它还提供了检查给定请求的实际来源、http方法和头的方法供以调用。用人话说:它就是具体封装跨域配置信息的pojo。

默认情况下新创建的CorsConfiguration它是不允许任何跨域请求的,需要你手动去配置,或者调用applyPermitDefaultValues()开启GET、POST、Head的支持~


几乎所有场景,创建完CorsConfiguration最后都调用了applyPermitDefaultValues()方法。也就是说你不干预的情况下,一个CorsConfiguration配置一般都是支持GET、POST、Head的


// @since 4.2
public class CorsConfiguration {
  // public的通配符:代表所有的源、方法、headers...
  // 若你需要使用通配符,可以使用此静态常量
  public static final String ALL = "*";
  private static final List<HttpMethod> DEFAULT_METHODS = Collections.unmodifiableList(Arrays.asList(HttpMethod.GET, HttpMethod.HEAD));
  // 默认许可所有方法
  private static final List<String> DEFAULT_PERMIT_ALL = Collections.unmodifiableList(Arrays.asList(ALL));
  // 默认许可这三个方法
  private static final List<String> DEFAULT_PERMIT_METHODS = Collections.unmodifiableList(Arrays.asList(HttpMethod.GET.name(), HttpMethod.HEAD.name(), HttpMethod.POST.name()));
  // ==========把这些属性对应上文讲述的响应头们对应,和W3C标注都是对应上的=========
  @Nullable
  private List<String> allowedOrigins;
  @Nullable
  private List<String> allowedMethods;
  @Nullable
  private List<HttpMethod> resolvedMethods = DEFAULT_METHODS;
  @Nullable
  private List<String> allowedHeaders;
  @Nullable
  private List<String> allowedHeaders;
  @Nullable
  private List<String> exposedHeaders;
  @Nullable
  private Boolean allowCredentials;
  @Nullable
  private Long maxAge;
  ... // 省略所有构造函数以及所有的get/set方法
  // 使用此方法将初始化模型翻转为以允许get、head和post请求的所有跨源请求的打开默认值开始
  // 注意:此方法不会覆盖前面set进去的值,所以建议此方法可以作为兜底调用。实际上Spring内部也是用它兜底的
  public CorsConfiguration applyPermitDefaultValues() {
    if (this.allowedOrigins == null) {
      this.allowedOrigins = DEFAULT_PERMIT_ALL;
    }
    if (this.allowedMethods == null) {
      this.allowedMethods = DEFAULT_PERMIT_METHODS;
      this.resolvedMethods = DEFAULT_PERMIT_METHODS.stream().map(HttpMethod::resolve).collect(Collectors.toList());
    }
    if (this.allowedHeaders == null) {
      this.allowedHeaders = DEFAULT_PERMIT_ALL;
    }
    if (this.maxAge == null) {
      this.maxAge = 1800L;
    }
    return this;
  }
  public CorsConfiguration combine(@Nullable CorsConfiguration other) { ... }
  // 根据配置的允许来源检查请求的来源
  // 返回值并不是bool值,而是字符串--> 返回可用的origin。若是null表示请求的origin不被支持
  @Nullable
  public String checkOrigin(@Nullable String requestOrigin) { ... }
  // 检查预检请求的Access-Control-Request-Method这个请求头
  public List<HttpMethod> checkHttpMethod(@Nullable HttpMethod requestMethod) { ... }
  // 检查预检请求的Access-Control-Request-Headers
  @Nullable
  public List<String> checkHeaders(@Nullable List<String> requestHeaders) {
}


这个POJO的配置,是servlet传统web以及reactive web所共用的,它提供有校验的基本方法。它的属性、校验原则和W3C的CORS标准所对应。


CorsConfigurationSource


它表示一个源,该接口主要是为请求提供一个CorsConfiguration。


public interface CorsConfigurationSource {
  // 找到此request的一个CORS配置
  @Nullable
  CorsConfiguration getCorsConfiguration(HttpServletRequest request);
}


此接口方法的调用处有三个地方:


  • AbstractHandlerMapping.getHandler()/getCorsConfiguration()
  • CorsFilter.doFilterInternal()
  • HandlerMappingIntrospector.getCorsConfiguration()


因为它可以根据request返回一个CORS配置。可以把这个接口理解为:存储request与跨域配置信息的容器。它的继承树如下:


image.png

首先需要说的便是cors包下的UrlBasedCorsConfigurationSource


UrlBasedCorsConfigurationSource


它位于org.springframework.web.cors包:它里面存储着path patterns和CorsConfiguration的键值对。


// @since 4.2
public class UrlBasedCorsConfigurationSource implements CorsConfigurationSource {
  // 请务必注意:这里使用的是LinkedHashMap
  private final Map<String, CorsConfiguration> corsConfigurations = new LinkedHashMap<>();
  private PathMatcher pathMatcher = new AntPathMatcher();
  private UrlPathHelper urlPathHelper = new UrlPathHelper();
  ... // 生路所有的get/set方法
  // 这里的path匹配用到的是AntPathMatcher.match(),默认是按照ant风格进行匹配的
  @Override
  @Nullable
  public CorsConfiguration getCorsConfiguration(HttpServletRequest request) {
    String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
    for (Map.Entry<String, CorsConfiguration> entry : this.corsConfigurations.entrySet()) {
      if (this.pathMatcher.match(entry.getKey(), lookupPath)) {
        return entry.getValue();
      }
    }
    return null;
  }
}


本类它是作为AbstractHandlerMapping(RequestMappingHandlerMapping)的默认跨域资源配置的管理类

相关文章
|
15小时前
|
API 网络架构
Amazon API Gateway CORS 实战
Amazon API Gateway CORS 实战
6 0
|
1天前
|
前端开发 API 数据安全/隐私保护
Web前端开发中的跨域资源共享(CORS)解决方案
【2月更文挑战第5天】在Web前端开发中,跨域资源共享(CORS)是一个常见的挑战。本文将探讨CORS的概念和原理,并介绍一些常用的解决方案,包括服务器端配置和前端处理方法,帮助开发者更好地应对跨域请求问题。
16 4
|
3天前
|
前端开发 数据安全/隐私保护 UED
探索前端开发中的跨域资源共享(CORS)
【2月更文挑战第3天】在当今Web开发中,跨域资源共享(CORS)扮演着至关重要的角色。本文将深入探讨CORS在前端开发中的作用和实践经验,带你解锁跨域访问的奥秘。
|
3天前
|
前端开发 安全 JavaScript
前端开发中的跨域资源共享(CORS)机制
【2月更文挑战第3天】 在前端开发中,跨域资源共享(CORS)机制是一个重要的安全性问题。本文将介绍CORS的概念、原理和实现方式,并探讨在前端开发中如何处理跨域资源请求,以及如何提高网站的安全性。
|
3天前
|
前端开发 JavaScript API
探索前端开发中的跨域资源共享(CORS)
【2月更文挑战第3天】在前端开发中,跨域资源共享(CORS)是一个至关重要的话题。本文将深入探讨CORS的概念、工作原理以及如何在前端项目中正确配置和处理跨域请求,帮助开发者更好地理解和应用CORS技术。
19 7
|
4天前
|
前端开发 开发者
前端开发中的跨域资源共享(CORS)解决方案探讨
【2月更文挑战第2天】跨域资源共享(CORS)是前端开发中常见的问题,本文将深入探讨CORS的原理及解决方案,包括简单请求、预检请求以及常用的CORS解决方案,为前端开发者提供深入的理解和应对CORS问题的有效方法。
11 1
|
24天前
|
存储 运维 安全
Java常用类和基础API
Java常用类和基础API
33 0
|
1月前
|
前端开发 JavaScript
CORS跨域资源共享及解决方案
CORS跨域资源共享及解决方案
24 0
|
1月前
|
JavaScript 前端开发 Java
Java其他: 解释一下跨域资源共享(CORS)。
Java其他: 解释一下跨域资源共享(CORS)。
29 0
|
2月前
|
前端开发 JavaScript 安全
JavaScript高级主题:什么是跨域资源共享(CORS)?
JavaScript高级主题:什么是跨域资源共享(CORS)?
26 0

相关产品

  • 云迁移中心