参考:https://cloud.tencent.com/developer/article/1703212
https://cloud.tencent.com/developer/article/1513473
一、CORS 介绍
CORS全称是Cross-Origin Resource Sharing,直译过来就是跨域资源共享。
- 从站点 A 请求站点 B 的资源的时候,由于浏览器的同源策略的影响,这样的跨域请求将被禁止发送;为了让跨域请求能够正常发送,我们需要一套机制在不破坏同源策略的安全性的情况下、允许跨域请求正常发送,这样的机制就是CORS
- 要理解域、资源和同源策略这三个概念
域
:指的是一个站点,由protocal、host和port三部分组成,其中host可以是域名,也可以是ip;port如果没有指明,则是使用protocal的默认端口
资源
:是指一个URL对应的内容,可以是一张图片、一种字体、一段HTML代码、一份JSON数据等等任何形式的任何内容
同源策略
:指的是为了防止XSS,浏览器、客户端应该仅请求与当前页面来自同一个域的资源,请求其他域的资源需要通过验证。 - 当协议、子域名、主域名、端口号中任意一个不相同时,都算作不同域
二、预检请求——OPTIONS
跨域请求流程:
1.访问另一个域的资源
2.有可能会发起一次预检请求(非简单请求,或超过了Max-Age)
3.发起实际请求
- 在CORS中,定义了一种预检请求,即preflight request,当实际请求不是一个简单请求时,会发起一次预检请求。预检请求是针对实际请求的 URL 发起一次OPTIONS请求,并带上下面三个headers:
Origin
:值为当前页面所在的域,用于告诉服务器当前请求的域。如果没有这个header,服务器将不会进行CORS验证。
Access-Control-Request-Method
:值为实际请求将会使用的方法
Access-Control-Request-Headers
:值为实际请求将会使用的header集合 - 如果服务器端CORS验证失败,则会返回客户端错误,即4xx的状态码。
- 否则,将会请求成功,返回200的状态码,并带上下面这些headers:
Access-Control-Allow-Origin
:允许请求的域,多数情况下,就是预检请求中的Origin的值
Access-Control-Allow-Credentials
:一个布尔值,表示服务器是否允许使用cookies
Access-Control-Expose-Headers
:实际请求中可以出现在响应中的headers集合
Access-Control-Max-Age
:预检请求返回的规则可以被缓存的最长时间,超过这个时间,需要再次发起预检请求
Access-Control-Allow-Methods
:实际请求中可以使用到的方法集合 - 浏览器会根据预检请求的响应,来决定是否发起实际请求。
三、CORS 配置的方式
Spring 提供了多种配置CORS的方式,有的方式针对单个 API,有的方式可以针对整个应用;有的方式在一些情况下是等效的,而在另一些情况下却又出现不同。
在仅仅引入Spring Web的情况下,实现3.2 3.4这两种方式它们的区别会在引入Spring Security之后会展现出来
- 假设我们有一个 API:
@RestController class HelloController { @GetMapping("hello") fun hello(): String { return "Hello, CORS!" } }
3.1 @CrossOrigin注解
用@CorssOrigin注解需要引入Spring Web的依赖,该注解可以作用于方法或者类,可以针对这个方法或类对应的一个或多个 API 配置CORS规则:
@RestController
class HelloController {
@GetMapping("hello"