前言
我们有很多种方式解决跨域请求
本篇为大家讲解使用CORS解决跨域
CORS又称跨域资源共享
它需要浏览器和服务器的同时支持
在开发过程中,浏览器并不会有过多的变化
服务器是关键,只有服务器实现了CORS接口,才可以进行跨域请求
CORS对于浏览器发过来的AJAX跨域请求分为两种:
简单请求和非简单请求
简单请求
所谓简单请求就是HEAD,GET,POST三种请求方式
浏览器会在在header信息里面多加一个字段:
key:origin
value:协议+域名+端口(如https://localhost:8080)
服务器根据对象里的origin值来决定是否同意这次请求
如果请求通过
请求通过后,服务器会在header里多增加几个字段:
Access-Control-Allow-Origin: https://localhost:8080
Access-Control-Allow-Credentials: true
Access-Control-Expose-Headers: Token
解释:
1.Credentials是否允许包含cookie,如果返回了true,那么浏览器发送请求体的时候要添加:
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;
如此这般,才能向服务器发送cookie
2.Access-Control-Expose-Headers是多返回的字段名,根据实际需求改变
如果请求失败
说明之前发送Origin的value不在许可范围内
服务器会返回一个正常的HTTP回应
浏览器发现,这个回应的头信息没有包含Access-Control-Allow-Origin字段
从而抛出一个无法跨域的异常(可能是200,所以无法识别)
非简单请求
简单请求的方法是Head,Get,Post
那么非简单请求的方法就是Put,Delete,或者Content-Type是application/json
非简单请求在发出CORS请求之前,会增加一次HTTP查询请求,也叫预检请求
预检请求成功了,浏览器才能发出XMLHttpRequest,否则报错
如果浏览器发现这是一个非简单请求
就会先发送一个预检请求:
OPTIONS /cors HTTP/1.1
Origin: http://localhost:8088
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: token
预测请求的方法名叫OPTIONS
Origin和简单请求一样
Access-Control-Request-Method是请求方法
Access-Control-Request-Headers是额外发送的头信息字段
(tip:预检请求一般缓存下来,以便不需要在每次请求都发送)
如果预检请求通过
我们来看下服务器发出的回应
HTTP/1.1 200 OK
Date: Nov, 01 Dec 2017 01:15:39 GMT
Server: Apache/2.0.61 (Unix)
Access-Control-Allow-Origin: http://localhost:8088
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: token
Content-Type: text/html; charset=utf-8
Content-Encoding: gzip
Content-Length: 0
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Content-Type: text/plain
如果预检请求失败
服务器会返回一个HTTP回应(没有CORS的头信息字段)
并在console打出not allowed by Access-Control-Allow-Origin
异常
预检请求通过以后
浏览器发每次出的CORS请求就和简单请求一样
会有一个origin字段
服务器每次回应都会有Access-Control-Allow-Origin
头信息字段
前后端代码实现
前端jQuery写法:
$.ajax({
type: "POST",
url: baseUrl + "/post",
dataType: 'json',
crossDomain: true,
xhrFields: {
withCredentials: true
},
data: {
name: "name_from_frontend"
},
success: function (response) {
console.log(response)// 返回的 json 数据
$("#response").val(JSON.stringify(response));
}
});
crossDomain: true是指开启跨域
后端mvc配置类:
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**/*").allowedOrigins("*");
}
}
这是spring4.2以上版本
如果是4.2以下的:
public class CrossDomainFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
response.addHeader("Access-Control-Allow-Origin", "*");// 如果提示 * 不行,请往下看
response.addHeader("Access-Control-Allow-Credentials", "true");
response.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
response.addHeader("Access-Control-Allow-Headers", "Content-Type");
filterChain.doFilter(request, response);
}
}
4.2以下还需加过滤器:
<filter>
<filter-name>CrossDomainFilter</filter-name>
<filter-class>com.javadoop.filters.CrossDomainFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CrossDomainFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
以上便是CORS请求的原理;
觉得还可以的请点个赞,赞不了也可以收藏下;
总之,谢谢阅读~
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。