js跨域解决方案

今天来说一说js跨域那五毛钱的事。首先,在了解跨域之前,我们来知道什么是同源策略
概念:同源策略是客户端脚本(尤其是Javascript)的重要的安全度量标准。它最早出自Netscape Navigator2.0,其目的是防止某个文档或脚本从多个不同源装载。这里的同源策略指的是:协议,域名,端口相同,同源策略是一种安全协议。指一段脚本只能读取来自同一来源的窗口和文档的属性。
那么跨域的概念的就显而易见:只要协议、域名、端口有任何一个不同,都被当作是不同的域。

JSONP跨域(get方式请求)

通过引入不同域url的js脚本文件(script标签的src属性),并且在请求url后面传递一个callback参数指定回调函数的函数名,且服务端将要返回的json数据参数形式传入客户端指定的回调函数之中,js文件执行的时候,负责调用回调函数。例如:

1
2
3
4
5
6
<script>
function dosomething(jsondata){
//获得后台返回会json数据
}
</script>

<script src="http://www.example.com/data.php?callback=dosomething"></script>

优点:

  • 不受同源策略限制,可以进行跨域访问资源;
  • 兼容性比ajax要好,因为不用去创建xhr对象或者activexobject对象;

缺点:

  • 只支持get请求,而不能支持post等其他方式的http请求;
  • 它只支持跨域HTTP请求这种情况,不能解决不同域的两个页面之间如何进行js交互调用的问题;

ajax跨域资源共享:CORS(可以实现post方式请求)

其基本的原理思想就是:利用自定义的HTTP头部添加一个Access-Control-Allow-Origin属性字段,来让浏览器与服务器进行沟通,从而决定请求或响应是应该成功还是失败。

现在假设站点 http://foo.example 的网页应用想要访问 http://bar.other 的资源。以下的 JavaScript 代码应该会在 foo.example 上执行:

1
2
3
4
5
6
7
8
9
10
var invocation = new XMLHttpRequest();
var url = 'http://bar.other/resources/public-data/';

function callOtherDomain() {
if(invocation) {
invocation.open('GET', url, true);
invocation.onreadystatechange = handler;
invocation.send();
}
}

现在浏览器向服务器发送跨站的请求,以下是http请求报文以及响应请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
GET /resources/public-data/ HTTP/1.1
Host: bar.other
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1b3pre) Gecko/20081130 Minefield/3.1b3pre
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Connection: keep-alive
Referer: http://foo.example/examples/access-control/simpleXSInvocation.html
Origin: http://foo.example


HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 00:23:53 GMT
Server: Apache/2.0.61
Access-Control-Allow-Origin: *
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: application/xml

[XML Data]

服务端返回请求头里面Access-Control-Allow-Origin:*表示服务器接受来自任何其他站点的跨站请求,这样http://example.com站点下的js脚本文件就能够接受到来自http://bar.other站点服务器返回的json数据,从而实现了一个简单的跨站请求过程。

参考学习资源:

https://segmentfault.com/a/1190000000718840
https://developer.mozilla.org/zh-CN/docs/Web/Security/Same-origin_policy
https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORS