跨域问题相信不少朋友都遇到过,八仙过海各显神通,解决的方法也有很多种,那我今天也来稍微扯一扯。
问题重现
先用nodejs写一个最简单的web后台
1 | // server.js |
在vps上运行以后web端请求正常:
在本地写一个html文件跨域请求
1 | <!-- local.html --> |
用chrome打开:
一个寻常的跨域问题就此构造完成。
note: 虽然跨域请求失败,但server端确实收到了请求,并成功打出了日志,可见浏览器对于跨域请求没有作限制,问题出在response到浏览器解析这一个环节。
使用charles抓包,发现hello world这条数据是成功被送到了客户端,那么就可以断定是浏览器在解析response头的时候作了限制。
问题解决
服务端方案
既然是Access-Control-Allow-Origin
的问题,chrome的调试器已经说得很清楚了,那就从这里开刀
server端代码修改如下:
1 | // server.js |
客户端请求结果:
跨域请求数据成功!
jsonp方案
jsonp方案也需要对server作一些修改:
1 | // server.js |
- 客户端方案1
1
2
3
4
5
6
7
8
9<!-- server获取的req.url: /?jsoncallback=jQuery1910832485890481621_1441186464213&_=1441186464214 -->
<!-- local.html -->
<script>
$.getJSON("http://x.x.x.x:6022?jsoncallback=?",
function(json){
console.log(json); // Hello World
}
);
</script> - 客户端方案2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25<!-- server获取的req.url: /?jsoncallback=jQuery19104387724103871733_1441186839654&{}&_=1441186839655 -->
<!-- local.html -->
<script>
$.ajax({
async:false,
url: 'http://x.x.x.x:6022',
type: "GET",
dataType: 'jsonp',
jsonp: 'jsoncallback',
data: '{}',
timeout: 5000,
beforeSend: function(){
console.log('beforeSend');
},
success: function (json) {//客户端jquery预先定义好的callback函数,成功获取跨域服务器上的json数据后,会动态执行这个callback函数
console.log(json); // Hello World
},
complete: function(XMLHttpRequest, textStatus){
console.log('complete');
},
error: function(xhr, a, b, c, d){
//请求出错处理
}
});
</script> - 客户端方案3
1
2
3
4
5
6
7
8<!-- server获取的req.url: /?jsonppppp=jsonpCallback -->
<!-- local.html -->
<script type="text/javascript">
function jsonpCallback(result) {
console.log(result);
}
</script>
<script type="text/javascript" src="http://x.x.x.x:6022?jsonppppp=jsonpCallback"></script>
以上这三种客户端方法都能成功获取跨域数据,总结如下
- 方案一和方案二本质上是一样的,方案一是方案二的一个高级封装
- jsonp只能是http get请求
- 三种方法的req.url不全相同
- 前两种方案的前端js回调函数是自动生成的,每次请求都不同,有一个全局id。第三种则没有,每次请求都是同一个函数对象