目录
跨域
为什么会有跨域
跨域问题 是浏览器对于ajax请求的一种安全限制:
一个页面发起的ajax请求,只能是于当前页同域名的路径
解决跨域问题的方案
-
jsonp
最早的解决方案,利用script标签可以跨域的原理实现
缺点:
-
需要服务器端的支持
-
只能发起GET请求
-
-
nginx反向代理
原理:利用nginx反向代理把跨域变为不跨域,支持各种请求方式
缺点:
-
需要在nginx进行额外配置,语义不清晰
-
-
CORS
规范化的跨域请求解决方案,安全可靠
优势:
-
在服务端控制是否允许跨域,可自定义规则
-
支持各种请求方式
缺点:
-
会产生额外的请求
-
CORS解决跨域
CORS是一个W3C标准,全称是“跨域资源共享”(Cross-orign resource sharing)
它允许浏览器向跨源服务器发出 XMLHttpRequest
请求,从而克服了AJAX只能同源使用的限制。
CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10
浏览器讲ajax请求分为两类:简单请求、特殊请求
简单请求
满足一下两大条件,就属于简单请求:
(1)请求方法是以下三种办法之一:
-
HEAD
-
GET
-
POST
(2)HTTP的头信息不超出以下几种字段:
-
Accept
-
Accept-Language
-
Content-Language
-
Last-Event-ID
-
Last-Event-ID
-
Content-Type只限于三个值:
-
application/x-www/form-urlencoded
-
multipart/form-data
-
text/plain
-
如果ajax请求是简单请求时,浏览器会在请求头重懈怠一个字段:Origin
// 当前请求属于哪个域(服务器根据这个只决定是否允许跨域)
Origin:http://manage.leyou.com
如果服务器允许跨域,会在响应头中携带一下信息:
// 可接受的域,是一个具体的域或者任意(*)
Access-Control-Allow-Orign:http://manage.leyou.com
// 是否允许携带Cookie
Access-Control-Allow-Credentials:true
特殊请求
不符合简单请求的条件,会被浏览器判定为特殊请求
特殊请求会在正式通信之前,增加一次HTTP查询请求,成为“预检”请求(preflight)
浏览器先询问服务器,当前网页所载的域名是否在服务器的许可名单之中,以及可以使用那些HTTP动词和头信息字段。只有得到肯定的答复,浏览器才会发出正式的XMLHttpRequest
请求,否则就报错
HTTP Request Demo:
OPTIONS /user HTTP/1.1
Origin:http://manage.leyou.com
Access-Control-Request-Method:PUT
Access-Control-Request-Headers:X-Custom-Header
Host:api.leyou.com
Accept-Language:en-US
与简单请求相比,除了Origin以外,特殊请求多了两个头:
-
Access-Control-Request-Methods:接下来会用到的请求方式
-
Access-Control-Request-Headers:会额外用到的头信息
服务器如果许可跨域,会发出响应:
HTTP/1.1 200 OK
Date: ...
Server: ///
Access-Control-Allow-Origin: http://manage.leyou.com
Access-Control-Allow-Credentials: true
// 允许访问的方式
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
// 允许携带的头
Access-Control-Allow-Headers: x-Custom-Header
// 课次许可的有效时长,单位是s,过期之前无需再预检
Access-Control-Allow-Max-Age: 3600
Content-Type: text/html;charset=utf-8
springboot解决跨域
@EnableWebMvc
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**") // 注册所有请求
.allowedOrigins("*")
.allowedMethods("GET", "POST", "PUT", "DELETE")
.allowCredentials(false)
.maxAge(3600);
}
}