ilife5 / life

life is a beautiful che~
4 stars 5 forks source link

高级浏览器中的跨域请求 #31

Closed ilife5 closed 9 years ago

ilife5 commented 9 years ago

高级浏览器中的跨域请求

缘由:浏览器出于安全考虑的同源策略(same-origin policy) 涉及范围:脚本,样式,图片,XHR以及需要http请求下载的资源 目的:解决xhr,webfont,webGL纹理(textures)以及使用drawImage向cancas上绘制图片

参考:Access_control_CORS

ilife5 commented 9 years ago

Simple requests:

Access-Control-Allow-Origin:决定资源可以被那些domain访问,可以参考webfont服务器的设置。

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(); 
  }
}
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]

服务端需要增加response报头:Access-Control-Allow-Origin: *

ilife5 commented 9 years ago

HTTP/1.1:OPTIONS方法支持通知server端将要request的类型以及其他头部内容,server端回复支持的request类型以及支持的其他头部内容。

Preflighted Request

以下条件成立时,属于Preflighted Request

var invocation = new XMLHttpRequest();
var url = 'http://bar.other/resources/post-here/';
var body = '<?xml version="1.0"?><person><name>Arun</name></person>';

function callOtherDomain(){
  if(invocation)
    {
      invocation.open('POST', url, true);
      invocation.setRequestHeader('X-PINGOTHER', 'pingpong');
      invocation.setRequestHeader('Content-Type', 'application/xml');
      invocation.onreadystatechange = handler;
      invocation.send(body); 
    }

......
OPTIONS /resources/post-here/ 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
Origin: http://foo.example
Access-Control-Request-Method: POST
Access-Control-Request-Headers: X-PINGOTHER

HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 01:15:39 GMT
Server: Apache/2.0.61 (Unix)
Access-Control-Allow-Origin: http://foo.example
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: X-PINGOTHER
Access-Control-Max-Age: 1728000
Vary: Accept-Encoding, Origin
Content-Encoding: gzip
Content-Length: 0
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Content-Type: text/plain

POST /resources/post-here/ 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
X-PINGOTHER: pingpong
Content-Type: text/xml; charset=UTF-8
Referer: http://foo.example/examples/preflightInvocation.html
Content-Length: 55
Origin: http://foo.example
Pragma: no-cache
Cache-Control: no-cache

<?xml version="1.0"?><person><name>Arun</name></person>

HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 01:15:40 GMT
Server: Apache/2.0.61 (Unix)
Access-Control-Allow-Origin: http://foo.example
Vary: Accept-Encoding, Origin
Content-Encoding: gzip
Content-Length: 235
Keep-Alive: timeout=2, max=99
Connection: Keep-Alive
Content-Type: text/plain

[Some GZIP'd payload]

服务端需要设置response报头回馈:

ilife5 commented 9 years ago

Credencials

HTTP Cookies and HTTP Authentication information

诉求:跨域请求需要附加Cookies以及HTTP认证信息,由于安全策略,跨域请求不能带着这些敏感信息。

浏览器端可以通过如下方式设置认证信息:

var invocation = new XMLHttpRequest();
var url = 'http://bar.other/resources/credentialed-content/';

function callOtherDomain(){
  if(invocation) {
    invocation.open('GET', url, true);
    invocation.withCredentials = true;
    invocation.onreadystatechange = handler;
    invocation.send(); 
  }
GET /resources/access-control-with-credentials/ 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/credential.html
Origin: http://foo.example
Cookie: pageAccess=2

HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 01:34:52 GMT
Server: Apache/2.0.61 (Unix) PHP/4.4.7 mod_ssl/2.0.61 OpenSSL/0.9.7e mod_fastcgi/2.4.2 DAV/2 SVN/1.4.2
X-Powered-By: PHP/5.2.6
Access-Control-Allow-Origin: http://foo.example
Access-Control-Allow-Credentials: true
Cache-Control: no-cache
Pragma: no-cache
Set-Cookie: pageAccess=3; expires=Wed, 31-Dec-2008 01:34:53 GMT
Vary: Accept-Encoding, Origin
Content-Encoding: gzip
Content-Length: 106
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Content-Type: text/plain

[text/plain payload]

因为cookie是双方作用的,server端可以通过set-Cookie 报头来同步浏览器端的cookie,所以浏览器端同样有限制:

ilife5 commented 9 years ago

HTTP Response Headers

Access-Control-Allow-Origin

wildcrads

Access-Control-Allow-Origin: *

origin

如果指定了具体的域名,需要在Vary报头中增加Origin值,告诉浏览器该值服务端经过处理。

Access-Control-Allow-Origin: http://xxx.com
Vary: Origin

Access-Control-Expose-Headers

暴露给浏览器的报文白名单

Access-Control-Expose-Headers: X-My-Custom-Header, X-Another-Custom-Header

Access-Control-Max-Age

用于通知浏览器preflighted请求可以被cached的时间

Access-Control-Max-Age: <delta-seconds>

Access-Control-Allow-Credentials

在preflighted请求中,用于告知浏览器Credentials是否有效。在正常请求中,决定该请求是否生效。

Access-Control-Allow-Credentials: true | false

Access-Control-Allow-Methods

在preflighted请求中,用于告知浏览器接受的方法列表

Access-Control-Allow-Methods: <method>[, <method>]*

Access-Control-Allow-Headers

在preflighted请求中,用于告知浏览器生效的headers列表

Access-Control-Allow-Headers: <field-name>[, <field-name>]*
ilife5 commented 9 years ago

The HTTP request headers

下面列出来仅和cross-site类型有关的请求

Origin

在请求或者preflighted请求中通知服务端发起请求页面的域名,不包含路径信息。

Origin: <origin>

Access-Control-Request-Method

在preflighted请求中告知服务端在真实的请求中将要发送何种类型的HTTP方法。

Access-Control-Request-Method: <method>

Access-Control-Request-Headers

在preflighted请求中告知服务端在真实的请求中将要发送何种类型的HTTP报头。

Access-Control-Request-Headers: <field-name>[, <field-name>]*
ilife5 commented 9 years ago

兼容性

desctop

Chrome Firefox (Gecko) Internet Explorer Opera Safari
4 3.5 8 (via XDomainRequest) 10 12 4

mobile

Android Chrome for Android Firefox Mobile (Gecko) IE Mobile Opera Mobile Safari Mobile
2.1 yes yes ? 12 3.2