CORS
什么是CORS?
CORS(Cross-Origin Resource
Sharing,跨域资源共享)是一种用于在浏览器中安全地允许跨域请求的机制。它规定了当一个网页请求访问另一个域(源)上的资源时,服务器必须显式允许这种访问。CORS通过设置特定的HTTP头部来控制哪些资源可以被哪些源访问
。
背景和问题
在Web应用中,浏览器出于安全考虑,默认会阻止从一个域(源)上的网页向另一个域请求资源,这被称为“同源策略”
。同源策略限制了从不同源加载的脚本的交互,防止了恶意网站窃取数据或执行未授权操作。
然而,实际开发中经常需要跨域请求资源,例如,前端应用需要从不同的API获取数据。CORS提供了一种机制,使服务器可以明确地告知浏览器,哪些跨域请求是被允许的。
CORS的工作原理
CORS通过以下几种HTTP头部来实现跨域资源共享:
Access-Control-Allow-Origin
:指定哪些源可以访问资源。例如,Access-Control-Allow-Origin: http://example.com
表示只有http://example.com
可以访问资源。可以设置为*
以允许所有源。Access-Control-Allow-Methods
:指定允许哪些HTTP方法。例如,Access-Control-Allow-Methods: GET, POST, PUT
。Access-Control-Allow-Headers
:指定哪些HTTP头部可以在实际请求中使用。例如,Access-Control-Allow-Headers: Content-Type
。Access-Control-Allow-Credentials
:指示是否允许发送Cookie或HTTP认证信息。设置为true
以允许。Access-Control-Expose-Headers
:指定哪些头部可以在响应中暴露给浏览器脚本。Access-Control-Max-Age
:指示结果可以被缓存多长时间(以秒为单位)。
简单请求与预检请求
CORS请求分为简单请求(Simple Requests)和预检请求(Preflight Requests)两种。
简单请求
简单请求是满足以下条件的请求:
- 使用以下方法之一:
GET
、HEAD
、POST
。 - 仅使用安全的HTTP头部字段:
Accept
、Accept-Language
、Content-Language
、Content-Type
(但Content-Type仅限于application/x-www-form-urlencoded
、multipart/form-data
、text/plain
)。
对于简单请求,浏览器会直接发送请求,并根据响应中的CORS头部决定是否允许跨域访问。
预检请求
CORS
pre-flight请求是一种以OPTIONS
方法发送的HTTP请求,浏览器在执行实际的跨域请求之前发送这个请求,以了解服务器是否允许使用特定的HTTP方法和头信息进行跨域请求。这个请求由浏览器自动发起,而不是由客户端代码(JavaScript)直接触发。目的就是以确认服务器是否允许跨域请求,避免未经授权的跨域访问
。如果服务器允许,该预检请求返回的响应中包含相应的CORS头信息,实际请求才会被发送。
预检请求包含以下头部:
Origin
:请求的来源域名。Access-Control-Request-Method
:实际请求将使用的方法。Access-Control-Request-Headers
:实际请求将使用的自定义头部字段(如果有)。
如果服务器允许请求,将在响应中返回相应的CORS头部,浏览器随后才会发送实际请求。
响应中包含以下头信息:
Access-Control-Allow-Origin
:允许访问的来源域名。Access-Control-Allow-Methods
:允许的HTTP方法列表。Access-Control-Allow-Headers
:允许的自定义头信息列表(如果有)。Access-Control-Max-Age
(可选):预检请求的结果可以缓存的时间。
如果预检请求的响应允许实际请求,则浏览器会继续发送实际的跨域请求。否则,实际请求会被浏览器阻止。
实例
假设一个前端应用位于http://example.com
,它需要访问位于http://api.example.com/data
获取资源。
预检请求
1 |
|
预检响应
1 |
|
实际请求
如果预检请求成功,浏览器将发送实际的跨域请求。
1 |
|
CORS处理
最后再来看一下CORS处理。
1 |
|
Spring会判断当前请求是否是CORSCross-Origin Resource Sharing,跨域资源共享)请求。它通过在处理链中添加CORS相关的拦截器来处理跨域请求。
如果请求是CORS预检请求(Pre-flight Request),则通过
getPreFlightHandlerExecutionChain方法返回一个专门处理预检请求的HandlerExecutionChain.
对于实际的CORS请求,通过getCorsHandlerExecutionChain
方法在处理链中添加一个CORS拦截器。
CORS 拦截器
CorsInterceptor
是实现跨域资源共享的核心拦截器。它会检查请求的CORS头部信息,并根据配置的CORS策略处理请求。
1 |
|
综上所述,Spring处理CORS请求的完整流程如下:
- 请求进入Spring MVC的DispatcherServlet。
- DispatcherServlet通过HandlerMapping查找处理器,并生成HandlerExecutionChain。
- 在HandlerExecutionChain中,根据请求的CORS配置添加相应的CORS拦截器(CorsInterceptor)。
- 如果是预检请求,返回专门的PreFlightHandler处理链。
- 请求通过HandlerExecutionChain处理,CORS拦截器在处理链的过程中应用CORS规则。
- 最终处理器处理请求,并返回响应。
通过这种方式,Spring MVC可以灵活而有效地处理各种CORS请求。
博客说明
文章所涉及的资料来自互联网整理和个人总结,意在于个人学习和经验汇总,不用于任何的商业用途。如有侵权,请联系本人删除。谢谢!