天天看点

新W3C标准中 AJAX 跨域实现以及隐患Cross-Origin Resource Sharing

标准也很无奈,标准很难做到 Secure By Default。

最新的W3C标准里是这么实现HTTP跨域请求的,

简单来说,就是跨域的目标服务器要返回一系列的Headers,通过这些Headers来控制是否同意跨域。

这些Headers有:

<a href="http://dev.w3.org/2006/waf/access-control/#syntax">4 Syntax</a>

<a href="http://dev.w3.org/2006/waf/access-control/#access-control-allow-origin">4.1 <code>Access-Control-Allow-Origin</code> HTTP Response Header</a>

<a href="http://dev.w3.org/2006/waf/access-control/#access-control-max-age">4.2 <code>Access-Control-Max-Age</code> HTTP Response Header</a>

<a href="http://dev.w3.org/2006/waf/access-control/#access-control-allow-credentials">4.3 <code>Access-Control-Allow-Credentials</code> HTTP Response Header</a>

<a href="http://dev.w3.org/2006/waf/access-control/#access-control-allow-methods">4.4 <code>Access-Control-Allow-Methods</code> HTTP Response Header</a>

<a href="http://dev.w3.org/2006/waf/access-control/#access-control-allow-headers">4.5 <code>Access-Control-Allow-Headers</code> HTTP Response Header</a>

<a href="http://dev.w3.org/2006/waf/access-control/#origin0">4.6 <code>Origin</code> HTTP Request Header</a>

<a href="http://dev.w3.org/2006/waf/access-control/#access-control-request-method">4.7 <code>Access-Control-Request-Method</code> HTTP Request Header</a>

<a href="http://dev.w3.org/2006/waf/access-control/#access-control-request-headers">4.8 <code>Access-Control-Request-Headers</code> HTTP Request Header</a>

在 Request 包和 Response 包中都有一些。

其中最敏感的就是 Access-Control-Allow-Origin

这个 Header, 他是W3C标准里用来检查该跨域请求是否可以被通过。 (Access Control Check)

跨域实现的过程大致如下:

从 http://www.a.com/test.html 发起一个跨域请求,

请求的地址为: http://www.b.com/test.php

如果 服务器B返回一个如下的header

Access-Control-Allow-Origin: http://www.a.com

那么,这个来自 http://www.a.com/test.html 的跨域请求就会被通过。

在这个过程中, request 还会带上这个header:

Origin: http://www.a.com

新W3C标准中 AJAX 跨域实现以及隐患Cross-Origin Resource Sharing

不过这里比较要命的是 Access-Control-Allow-Origin 的值可以是通配符 *

如果是 * 的话,就可以接收来自任意source origin的请求。

我已经可以想象到以后这个特性被程序员滥用以及被用来制作后门的可怕后果了!

在 Firefox 3.1 Beta 2 上抓包如下:

GET http://www.b.com/test.php HTTP/1.1

Host: www.b.com

User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.1b2) Gecko/20081201 Firefox/3.1b2 Paros/3.2.13

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8

Accept-Language: zh-cn,zh;q=0.5

Accept-Charset: gb2312,utf-8;q=0.7,*;q=0.7

Keep-Alive: 300

Proxy-Connection: keep-alive

Referer: http://www.a.com/test.html

Cache-Control: max-age=0

HTTP/1.1 200 OK

Date: Thu, 15 Jan 2009 06:28:54 GMT

Server: Apache/2.0.63 (Win32) PHP/5.2.6

X-Powered-By: PHP/5.2.6

Access-Control-Allow-Origin: *

Content-Length: 28

Content-Type: text/html

Cross Domain Request Test!

两段代码大致如下:

www.a.com/test.html:

&lt;script&gt;

var client = new XMLHttpRequest();

client.open("GET", "http://www.b.com/test.php");

client.onreadystatechange = function() { }

client.send(null);

&lt;/script&gt;

www.b.com/test.php:

&lt;?php

header("Access-Control-Allow-Origin: *");

?&gt;

除了这个Header外,还可以通过一些其他的Header 来控制比如 Method, 时间等,可以参考标准,不在此赘述。

出于安全考虑,跨域请求不能访问document.cookie 对象

对于IE8 Beta 2, 则是通过 XDomainRequest 来实现的这个跨域请求

比如类似如下代码就可以实现了:

var request = new XDomainRequest();

request.open("GET", xdomainurl);

request.send();

也要求对方服务器返回这个头才行。

IE的开发者今天公布了一段小视频:

<a href="http://ieblog.members.winisp.net/images/XdomainRequest-small.wmv">http://ieblog.members.winisp.net/images/XdomainRequest-small.wmv</a>

目前,支持这种跨域实现的要求

Firefox 3.1 Beta2

IE 8 Beta2

等到普及还有一段时间。

最后再加一个Firefox3.1实现跨域的说明文档:

<a href="https://developer.mozilla.org/En/HTTP_access_control">https://developer.mozilla.org/En/HTTP_access_control</a>