SpringMvc解决跨域问题的源码汇总。

server/2025/1/15 10:32:19/

看本文章前,需了解跨域的缘由。

其次,了解RequestMapping的基础原理

最后我们来解析SpringMvc是如何处理跨域问题的。

                                    跨域信息配置

SpringMvc分为全局级别和局部级别两种,全局级别就是任何跨域请求都起作用。

                                          全局级别

全局级别就是在配置HandlerMapping时,从源码分析可知,AbstractHandlerMapping是requestMapping的第一子类,其内部拥有属性globalCorsConfigSource,这个属性对应的对象是一个实现了org.springframework.web.cors.CorsConfigurationSource的对象,通过暴露org.springframework.web.servlet.handler.AbstractHandlerMapping#setCorsConfigurations方法,可以直接向globalCorsConfigSource注入url与跨域配置信息。至于该方法如何调用,则是在Springboot里有所体现。

                                          局部级别

而局部级别的,就是针对request的url对应的特定handler起作用。从RequestMapping的查找我们可以得知,springmvc在获取handler的过程中,有两种解析方式,一种是对象级别的,一种是方法级别的。

                                                针对对象级别的

SpringMvc提供了org.springframework.web.cors.CorsConfigurationSource接口,也就是说,如果你的handler实现了org.springframework.web.cors.CorsConfigurationSource,那么当有跨域出现的请求时,会优先使用CorsConfigurationSource的实现来实现。

                                               针对方法级别的

优先使用在方法上注解的org.springframework.web.bind.annotation.CrossOrigin,其次使用所属bean上注解的org.springframework.web.bind.annotation.CrossOrigin。它们会将这个注解信息解析成CorsConfigurationSource的子类。

                                    如何处理跨域

首先,根据浏览器跨域规则我们可以知道,对于跨域资源,浏览器会有两种行为。

一种行为是,假如是一个简单的Get跨域请求,浏览器将直接发起请求。

另外一种行为是,假如是一个使用 PUTDELETE 方法的请求,浏览器会发送一个预检请求,所谓的预检请求,指的就是发送一个请求方法为OPTIONS的请求。

针对这两种行为,SpringMvc有不同的处理方式。

                                             OPTIONS请求方法

针对OPTION的跨域请求方法,springMvc底层会默认匹配一个PreFlightHandler的handler,这个handler作用也很简单,就是查找上面的CorsConfigurationSource,获取这个url匹配的跨域配置CorsConfiguration,并且查看做如下匹配

1.请求的Request的Origin头的值,是否与CorsConfiguration里的allowedOrigins里匹配,匹配则放行。

2.再次检查Access-Control-Request-Method头的值,是否与CorsConfiguration里allowedMethods是否匹配,匹配则放行。

3.再次检查Access-Control-Request-Headers头的值,是否与CorsConfiguration里allowedHeaders是否匹配,匹配则放行。

如果上面任意一步无法做到匹配,就会直接返回一个Response,状态码为403,而值的信息Invalid CORS request。

如果以上都通过了,则直接会设置如下的相应头:

Access-Control-Allow-Origin:即Request请求里的Origin头
Access-Control-Allow-Methods:即Request里的Access-Control-Request-Method对应的值,且该值必须被跨域允许的,比如,传了GET、POST,但是跨域配置里,即CorsConfiguration的allowedMethods为GET,则该值就会是GET
Access-Control-Allow-Headers:即Request里的Access-Control-Request-Headers对应的值,且该值必须被跨域允许的,比如,传了COOKIE、TOKEN等,但是跨域配置里,即CorsConfiguration的allowedHeaders为TOKEN,则该值就会是TOKEN
Access-Control-Expose-Headers:即根据跨域配置里,即CorsConfiguration的exposedHeaders的值,这个值的作用是什么呢?那就是告诉浏览器,你接到这个相应的时候,可以暴露哪些头信息,比如自定义了一个Token头,但是如果你不指定的话,浏览器是不会展示这个头给用户的,即便,你在响应里设置了这个头。
Access-Control-Allow-Credentials:该值是告诉浏览器,是否允许发送敏感信息,这些敏感信息包含cookie、TLS 客户端证书,或包含用户名和密码的认证标头等。为true则是允许。

Access-Control-Max-Age:用于指定预检请求(preflight request)的结果可以缓存多长时间,以减少浏览器发送预检请求的次数,从而提升跨域请求的性能。

                                            直接请求方法

对于非预检请求,springMvc会为这个handler生成一个HandlerInterceptor,即org.springframework.web.servlet.handler.AbstractHandlerMapping.CorsInterceptor。

这个拦截器的org.springframework.web.cors.DefaultCorsProcessor#processRequest里对请求是否跨域进行处理。

1.请求的Request的Origin头的值,是否与CorsConfiguration里的allowedOrigins里匹配,匹配则放行。

2.再次检查Access-Control-Request-Method头的值,是否与CorsConfiguration里allowedMethods是否匹配,匹配则放行。

如果以上都通过了,则直接会设置如下的相应头:

Access-Control-Allow-Origin:即Request请求里的Origin头
Access-Control-Expose-Headers:即根据跨域配置里,即CorsConfiguration的exposedHeaders的值,这个值的作用是什么呢?那就是告诉浏览器,你接到这个相应的时候,可以暴露哪些头信息,比如自定义了一个Token头,但是如果你不指定的话,浏览器是不会展示这个头给用户的,即便,你在响应里设置了这个头。
Access-Control-Allow-Credentials:该值是告诉浏览器,是否允许发送敏感信息,这些敏感信息包含cookie、TLS 客户端证书,或包含用户名和密码的认证标头等。为true则是允许。

如果以上有任意匹配不通过,则直接通过拦截器返回CorsInterceptor返回false,即不再继续处理请求。

                                                 CorsConfiguration

从上面我们可以知道,无论你用那种方法,跨域的配置信息始终存放在org.springframework.web.cors.CorsConfigurationSource的子类中,而这个类SpringMvc默认提供的实现是org.springframework.web.cors.UrlBasedCorsConfigurationSource。org.springframework.web.cors.UrlBasedCorsConfigurationSource则是非常简单,就是根据url查找到对应的CorsConfiguration对象。

                                   

CorsConfiguration内部存储着如下信息:
allowedOrigins:即它指定了跨域Request的Access-Control-Allow-Origin的头信息,如果这个属性里不包含Access-Control-Allow-Origin,就代表跨域不允许。
allowedMethods:即它指定了跨域Request的Access-Control-Request-Headers的头信息,如果这个属性里不包含Access-Control-Request-Headers,就代表跨域不允许。
allowedHeaders:即它指定了跨域Request的Access-Control-Request-Method的头信息,如果这个属性里不包含Access-Control-Request-Method,就代表跨域不允许

exposedHeaders:Access-Control-Expose-Headers

 

                                                      


http://www.ppmy.cn/server/158523.html

相关文章

构建高效的进程池:深入解析C++实现

构建高效的进程池:深入解析C实现 在高性能计算和服务器应用中,进程池(Process Pool)是一种重要的设计模式。它通过预先创建和维护一定数量的子进程来处理大量的任务请求,从而避免频繁地创建和销毁进程带来的开销。本文…

创建和管理表

第十章: 创建和管理表 1.基础知识 1.1一条数据的存储规则 MySQL数据库从大到小依次是数据库函数,数据库,数据表,数据表的行与列 1.2标识符命名规则 数据库名 表名不得超过30个字符,变量名限制为29个 必须只能包括A-Z,a-z,0-9,_共63个字符 数据库名,表名,字段名等对象名中间…

Level2逐笔成交逐笔委托毫秒记录:今日分享优质股票数据20250114

逐笔成交逐笔委托下载 链接: https://pan.baidu.com/s/18YtQiLnt06cPQP1nRXor0g?pwd4k3h 提取码: 4k3h Level2逐笔成交逐笔委托数据分享下载 基于Level2的逐笔成交和逐笔委托数据,这种毫秒级别的记录能分析出许多关键信息,如庄家意图、虚假动作&#…

vue实现淘宝web端,装饰淘宝店铺APP,以及后端设计成能快速响应前端APP

一、前端实现 实现一个类似于淘宝店铺的装饰应用(APP)是一个复杂的任务,涉及到前端界面设计、拖放功能、模块化组件、数据管理等多个方面。为了简化这个过程,我们可以创建一个基本的 Vue 3 应用,允许用户通过拖放来添…

PHP:构建高效Web应用的强大工具

在当今的数字化时代,Web应用已经成为各行各业不可或缺的一部分。而在众多的编程语言中,PHP(Hypertext Preprocessor)凭借其简单易学、功能强大、兼容性高等特点,成为了构建Web应用的热门选择。本文将深入探讨PHP的优势…

uniapp 绘制五星评分 精确到半星

uniapp 绘制五星评分 精确到半星 对比上一篇博客 这个很简单上组件 <template><div :class"[imgTypeother?image-box:image-box1]"><img :class"[imgTypeother?image:image1]" v-for"(el,i) in value" :key"i" :sr…

Java 面试中的高频算法题详解

&#x1f496; 欢迎来到我的博客&#xff01; 非常高兴能在这里与您相遇。在这里&#xff0c;您不仅能获得有趣的技术分享&#xff0c;还能感受到轻松愉快的氛围。无论您是编程新手&#xff0c;还是资深开发者&#xff0c;都能在这里找到属于您的知识宝藏&#xff0c;学习和成长…

字符串算法篇——字里乾坤,算法织梦,解构字符串的艺术(下)

文章目录 前言第一章&#xff1a;最长公共前缀1.1 题目链接&#xff1a;https://leetcode.cn/problems/longest-common-prefix/description/1.2 题目分析&#xff1a;1.3 思路讲解&#xff1a;1.4 代码实现&#xff1a; 第二章&#xff1a;最长回文子串2.1 题目链接&#xff1a…