一、背景
跨域问题是发生在前端的问题,是指前端在访问不同域名或端口或协议的地址时候,由于浏览器的同源策略的约束,所以会产生跨域问题。
如下 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"); } }
文章评论