跨域请求的几种方式

AJAX 不能发送跨域请求(不符合同源策略的请求),但是项目中有时需要异步请求跨域的地址,这时简单的 AJAX 不能满足要求。

同源策略:URL 的协议、域名、端口全部一致。

jsonp

  JSONP(JSON With Padding)不是 AJAX,它是一种非官方的解决跨域请求问题的方式。
  JSONP 利用 HTML 中 script 标签不受同源策略影响,可以跨域请求资源,同时在资源加载后立即执行的特点,实现跨域请求。

js原生实现jsonp

通过动态生成 script 标签,将要请求的地址添加到 script 标签的 src 属性,然后将该 script 标签添加到页面。

页面代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<body>
<button id="btn01">JSONP</button>
</body>

<script type="text/javascript">

var btn01 = document.getElementById("btn01");

btn01.onclick = function() {
//创建一个script标签
var script = document.createElement("script");
//设置script标签src属性
script.src = "http://127.0.0.1:3000/testJSONP?callback=abc";
//将标签放到body中
document.body.appendChild(script);
};

function abc(data) {
alert(data);
}

</script>

url 地址后面的参数 callback 是指定一个回调函数,用来处理请求得到的数据。

后台node代码

1
2
3
4
5
6
7
8
9
app.get("/testJSONP",function (req , res) {
console.log("已经收到请求~~~");
var data = '这是服务器返回的内容';

// 得到参数-回调函数名
var callback = req.query.callback;
// 返回回调函数的调用,并将返回数据作为实参传递给回调函数
res.send(callback+"('"+ data +"')");
});

jQuery实现jsonp

  jQuery 中的 getJSON 方法可以用来发送 JSONP 请求,该方法的使用和 jQuery 的 get、post 方法的调用方式基本相同。
  需要注意的是,url 地址后需要添加参数 callback,callback 的值是一个 ?,jQuery 将自动替换 ? 为正确的函数名,以执行回调函数。

代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
$.getJSON("https://api.douban.com/v2/movie/in_theaters?callback=?", function(data) {

// 处理豆瓣热门电影接口返回的数据,显示到页面
var sub = data.subjects;
for (var i = 0; i < sub.length; i++) {
//将内容添加到div中
$("#box1").append(
"<li>" + sub[i].title + "<br />" +
"<img src='" + sub[i].images.large + "' >" +
"</li>"
);
}
});

JSONP的局限性

JSONP 只能发送 get 请求,而不能发送 post 请求。

CORS

  Cross-Origin Resource Sharing,跨域资源共享。CORS 是官方的跨域解决方案,相比 JSONP 更能更加全面,也更加灵活。
  使用 CORS 跨域在客户端基本不需要做任何操作,发送正常的 AJAX 请求即可,只需要修改一下服务器的代码。

  当发送的 AJAX 请求是跨域请求时,浏览器会自动在请求头信息中,添加一个 Origin 字段,Origin 字段会告诉服务器请求发送的来源(协议+域名+端口)。服务器根据 Origin 的值决定是否允许该跨域请求,默认情况是不允许的。
  我们可以在服务器中设置一个响应头 Access-Control-Allow-Origin,值为允许发送跨域请求的地址。浏览器判断该响应头中是否包含 Origin 的值,如果包含浏览器则处理响应,不包含浏览器直接驳回,无法得到响应数据。

node 代码:

1
res.set('Access-Control-Allow-Origin', 'http://localhost:3000');

如果接受任何域名的请求,可以将该字段的值设置为 * 。

1
res.set('Access-Control-Allow-Origin', '*');

CORS 的局限性

IE 9 及以下版本IE浏览器,不支持通过 XMLHTTPRequest 来发送跨域请求。

CORS 和 JSONP 的对比

  • CORS 除了 GET 方法外,也支持其它的 HTTP 请求方法如 POST、 PUT 等。
  • CORS 可以使用 XmlHttpRequest 进行传输,所以它的错误处理方式比 JSONP 好。
  • JSONP 可以在不支持 CORS 的老旧浏览器上运作。

XDR

在 IE8、IE9 浏览器中,需要使用 XDomainRequest 对象来发送跨域请求。

ajax 请求代码:

1
2
3
4
5
6
var xdr = new XDomainRequest();
xdr.open('get', 'http://127.0.0.1:3000/getJsonp');
xdr.send();
xdr.onload = function () {
alert(xdr.responseText);
}

-------------本文结束感谢您的阅读-------------
Fork me on GitHub