一、背景
跨域问题是发生在前端的问题,是指前端在访问不同域名或端口或协议的地址时候,由于浏览器的同源策略的约束,所以会产生跨域问题。
如下 ajax 请求不同端口的地址,就会出现 403:
$.ajax({
type: "get",
url: "http://localhost:9091/rest/jsonp",
dataType: "json",
success: function(val) {
console.log(val);
}
}); 
二、jsonp 解决跨域
此法很简单,前端和后端分别做点小改动就可。
1)前端修改
就是将 ajax 请求的 datatype 设置成 jsonp 即可,如下:

2)后端修改
后端只需要添加配置类即可,如下(此处是 springboot):
/**
* Created by Jet on 2017/12/10.
*/
@ControllerAdvice
@SpringBootConfiguration
public class JsonAdvice extends AbstractJsonpResponseBodyAdvice{
public JsonAdvice(){
// 这样如果请求中带 callback 参数,Spring 就知道这个是 jsonp 的请求了
super("callback");
}
}3)效果

地址后面会自动生成 callback 参数,当然,这就意味着你也可以手动定义 callback 函数来指定回调函数。
4)原理
其实底层就是通过动态创建 <script> 标签,然后把 src 指向服务端地址,而这个地址后面的参数 callback 就是回调函数,
最主要的其实是因为: <script>标签不受同源策略的约束,
5)弊端
此法很巧妙,很巧妙,但是 <script> 标签是只能发生 get 请求的,所以,jsonp 只能用来解决 get 请求的跨域问题。
三、CORS 解决跨域
1)简述
既然 jsonp 有弊端,那么 post 等其余请求该如何解决跨域问题呢?很简单,此处介绍 CORS。
CORS:Cross-Origin Resource Sharing
2)浏览器支持
但是对浏览器有版本的要求,如下(其实目前大部分 web 应用都要求只是 IE8 了):
- Chrome 3+
Firefox 3.5+
Opera 12+
Safari 4+
Internet Explorer 8+
3)前端实现
$.ajax({
type: "post",
url: "http://localhost:9091/rest/jsonp",
dataType: "json",
crossDomain: true, // 使用跨域请求
xhrFields: {
withCredentials: true // 把 cookie 带过去了,不然我们连 session 都没法维护
},
success: function(val) {
console.log(val);
}
});如上,要注意 withCredentials 设置为 true,将 cookie 带过去,否则会载坑。
4)后端实现
后端添加一条配置即可:
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
//放行哪些原始域
.allowedOrigins("*")
//是否发送Cookie信息
.allowCredentials(true)
//放行哪些原始域(请求方式)
.allowedMethods("GET","POST", "PUT", "DELETE")
//放行哪些原始域(头部信息)
.allowedHeaders("*")
//暴露哪些头部信息(因为跨域访问默认不能获取全部头部信息)
.exposedHeaders("Header1", "Header2");
}
}

文章评论