跨域:指的是浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器施加的安全限制。
同源是指,域名,协议,端口均相同,只要有一个不同,就是跨域。
跨域会阻止什么操作?
浏览器是从两个方面去做这个同源策略的,一是针对接口的请求,二是针对Dom的查询。
解决跨域的方法:
1. CORS
服务器设置响应头:
response.setHeader("Access-Control-Allow-Origin", "*")
(这样可能引起CSRF攻击,一般设置成对应的域名就行,response.setHeader(“Access-Control-Allow-Origin”, “http:localhost:8080/”) )
fetch的option加上 mode:“cors”。
2.jsonp
jsonp的方式,注意这种方式只能发送get请求,就算指定为post,最后发送的还是get,且跟上面方式一样,也需要服务器的配合支持。
1、 jsonp发送的并不是ajax请求;
2、 利用动态创建一个script标签,因为script标签是没有同源策略限制的,是可以跨域的;
3、 把这个script标签的src指向我们请求的服务端地址,这个地址会携带一个参数:callback ,一个回调函数,服务端会把数据通过这个回调函数返回给客户端,但是客户端没有这个函数怎么接收呢?所以在发送请求之前,要在全局(window)注册这样一个方法,利用这个方法,来获得数据;
4、 这个回调函数名需要跟服务端约定好,是一致的。
如果让我们用原生js实现一个jsonp,那就是这样:
<script>
//指定的回调函数
function showData (result) {
var data = JSON.stringify(result); //json对象转成字符串
$("#text").val(data);
}
$(document).ready(function () {
$("#btn").click(function () {
//向头部输入一个脚本,该脚本发起一个跨域请求
$("head").append("<script src='http://localhost:9090/student?callback=showData'><\/script>");
});
});
</script>
后端一是获取到前端传过来的回调函数名称,二是获取到数据,最后把数据用回调函数包围住,执行这个前端的这个回调函数。我们就可以利用前端这个事先全局注册的回调函数来显示操作数据了。
然后再分析一下jQuery关于jsonp的实现。
1.最简单的方式:
$.ajax({
type:"GET",
url:"http://www.xxx.com/getMySeat", //访问的链接
dataType:"jsonp", //数据格式设置为jsonp
success:function(data){ //成功的回调函数
alert(data);
},
error: function (e) {
alert("error");
}
});
服务端代码不变,最简单的方式,只需配置一个dataType:‘jsonp’,就可以发起一个跨域请求。jsonp指定服务器返回的数据类型为jsonp格式,可以看发起的请求路径,自动带了一个callback=xxx,callback是自己不手动设置参数名字的默认值,xxx是jquery随机生成的一个回调函数名称。
这里的success就跟上面的showData一样,如果有success函数则默认success()作为回调函数。
2.回调函数你可以写到script下(默认属于window对象),或者指明写到window对象里,看jquery源码,可以看到jsonp调用回调函数时,是调用的window.callback。
然后看调用结果,发现,请求时带的参数是:callback=showData;调用回调函数的时候,先调用了指定的showData,然后再调用了success。所以,success是返回成功后必定会调用的函数,就看你怎么写了。
3代理服务器
跨域问题是浏览器的同源策略限制,服务器之间是没有的,那我们先把请求给我们的代理服务器,再让我们的代理服务器去调用这个接口,在发送给前端就可以了。
前端:
代理服务器(node):
注意服务器返回的数据在response.data里,然后发送给前端的响应res。
(后来我前后端设置的端口不同,代理服务器也要设置Access-Control-Allow-Origin的头为 *)