❝以下内容来自于《Sping Boot+Spring Cloud+Vue+Element实战》第九章节:跨域解决方案
❞
跨域是什么
现代浏览器为了保证数据安全,不同源的客户端甲苯在没有明确授权的情况下,不能读写对方浏览器的资源,这就是同源策略
,这是浏览器安全的基础。
一个URL
中协议
,域名
,端口
都相同,这就是同源
以百度地址:http://www.baidu.com 为例,判断一下以下几种URL是否和百度地址同源
- http://www.baidu.com/abc.html 协议,域名,端口相同,属于
同源
- https://www.baidu.com/ 协议不同(https),不同源
- http://www.baidu.com:9090 端口不同,不同源
- http://www.baiduABC.com/ 域名不同,不同源
- ...
根据浏览器的同源策略
,不同源的脚本是不能操作其它源的资源,要想获取其它源下的资源,就面临跨域问题。不同源之间的网站之间互相发送AJAX请求,就要通过跨域方案来解决。
CORS
为了解决浏览器跨域的问题,W3C提出了跨域资源共享方案,即CORS(Corss-Origin-Resources Sharing)。
CORS可以在不破坏现有的规则下,通过后端服务器(前端也可以实现)实现CORS接口,从而实现跨域通信。CORS将请求分文两类:简单请求
和非简单请求
,分别对跨域通信进行支持。
简单请求
在CORS出现之前,发哦是哪个HTTP请求时在信息头
(Headers)中不能包含任何自定义字段,而且HTTP信息不能超过以下几个字段:
- Accept
- Accept-Language
- Content-Language
- Last-Event-ID
- Content-Type(只有application/x-www/form/urlencoded,multipart.form-data,text/plain 3种类型)
例如下面这样的一个简单请求的案例:
GET /test HTTP/1.1
Accept: * / *
Accept-Encoding: gzip,deflate,sdch,br
Origin: http://www.test.com
Host: www.test.com
对于简单请求,CORS的策略是请求时在头部增加一个Origin字段,服务器收到后,根据该字段判断是否允许该请求的访问
- 允许访问,在HTTP头部中添加Access-Control-Allow-Origin字段,返回正确结果
- 拒绝访问,头部信息中「不加」Access-Control-Allow-Origin
另外还有几个字段用于描述CORS返回结果:
- Access-Control-Allow-Credentials:可选,用户是否可以发送,处理cookie
- Access-Control-Expose-Headers:可选,可以让用户拿到的字段。
以下几个字段无论设置与否,用户均可以拿到:
- Cache-Control
- Content_language
- Content-Type
- Expries
- Last-Modified
- Pargma
非简单请求
对于非简单请求,浏览器会在真实请求发出前增加一次OPTION
请求,称之为预检请求
(preflight request)。预检请求将真实的请求信息(包括请求方法,自定义头部字段)添加到HTTP头部信息字段中,询问服务器是否允许。
例如下面一个GET请求
OPTIONS /test HTTP1.1
Orgin: http://www.test.com
Acess-Control-Request-Method: GET
Access-Contol-Reauest-Headers: X-Custom-Header
Host: www.test.com
与CORS相关的字段:
- 请求使用HTTP方法:Acess-Control-Request-Method
- 包含自定义字段:Access-Contol-Reauest-Headers
服务器收到请求时,需要分别对Origin,Acess-Control-Request-Method,Access-Contol-Reauest-Headers进行验证,验证通过后,会在返回的HTTP头部中添加:
- Access-Control-Allow-Origin: Http://www.test.com
- Acess-Control-Request-Methods: GET,PUT,POST,DELETE 真实请求允许的方法
- Access-Contol-Reauest-Headers: X-Custom-Header 服务器允许使用的字段
- Access-Contol-Reauest-Credentials: true 是否允许用户发送,处理cookie
- Access-Contol-Reauest-Max-Age: 172800 预检请求的有效期,单位秒。有效期内,不会发送重复的预检请求
当通过了预检请求后,浏览器才会发送真实的请求到服务器。实现了跨域资源的访问。
CORS后端实现
后端CORS方案实现如下:
/**
* 跨域实现
*/
@Configuration
public class CorsConfig implements WebMvcConfigurer {
public void addCorsFilter(CorsRegistry registry){
registry.addMapping("/**") // 允许跨域访问的路径
.allowedOrigins("*") // 允许跨域访问的源 *:代表所有域名都可以跨域访问
.allowedMethods("*") // 允许请求的方法 *:表示"GET","POST","PUT","DELETE"
.maxAge(168000) // 预检间隔时间
.allowedHeaders("*") // 允许头部携带任何信息
.allowCredentials(true); // 是否发送cookie true:允许携带cookie false:不允许
}
}
本文使用 mdnice 排版