ajax cors html,Ajax 跨域(CORS)请求中的预检请求

关于预检请求

定义:预检请求(Preflighted requests )是浏览器发起跨域请求时,通过OPTIONS方法询问服务器对跨域请求的支持情况(支持的包含请求方法、请求头、数据类型)。

6c1555302777729326ca3efa0910d9ec.png

触发预检请求的三类条件:

默认情况下,跨域请求只支持GET,HEAD,POST方法,如果不是这三个请求方法(比如:PUT、DELETE、CONNECT、OPTIONS、TRACE和PATCH),那么将触发预检请求

默认情况下,浏览器跨域请求时,会自动添加的请求头(HOST,Referer,Connection、Accept、User-Agent,Accept-Languange,Accept-Encoding,Accept-Charset和Content-Type),这些请求中还有其他请求头时,那么将触发预检请求。

如1、2所说的情况排除在外的条件下,跨域请求是,浏览器支持的Content-Type值为application/x-www-form-urlencoded,multipart/form-data和text/plain。如果是其他数据类型(如application/json,text/xml...),那么将触发预检请求。

下面通过一个Ajax跨域请求来验证

var xhr= new XMLHttpRequest();

var url = 'http://bar.other/resources/post-here/';

var body = '<?xml  version="1.0"?>Arun';

function callOtherDomain(){

if(invocation)

{

xhr.open('POST', url, true);

xhr.setRequestHeader('X-PINGOTHER', 'pingpong'); //自定义的Header

xhr.setRequestHeader('Content-Type', 'application/xml'); //特殊的文档类型

xhr.onreadystatechange = function(){};

xhr.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, Content-Type

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, Content-Type

Access-Control-Max-Age: 86400

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"?>Arun

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]

我们看到,首次发起的是OPTIONS请求,因为OPTIONS请求的作用本身就是询问服务器的请求,他这里询问浏览器是否支持如下条件请求

Access-Control-Request-Method: POST

#是否支持POST

Access-Control-Request-Headers: X-PINGOTHER, Content-Type

#是否支持X-PINGOTHER自定义请求头的内容,Content-Type可能是其他值,因此有必要询问

服务器回应是

Access-Control-Allow-Origin: http://foo.example

#支持foo.example域

Access-Control-Allow-Methods: POST, GET, OPTIONS

#支持的方法POST,GET,OPTIONS,实际上OPTIONS本身就支持

Access-Control-Allow-Headers: X-PINGOTHER, Content-Type

#支持的请求头,Content-Type是特殊的类型时,会触发预检,因此,这里最好加上Content-Type

Access-Control-Max-Age: 86400

#支持的缓存时间

如果满足以上条件,浏览器会自动发起提交之前没提交的数据,否则拒绝提交数据。

关于withCredentials

在跨域请求中,类似Cookie等敏感信息一般不会跨域传输,但是在服务器允许的情况下,Cookie会被发送

注意:Cookie的发送需要服务器允许才行,此外,跨域js所处的环境必须是线上环境【服务器环境】。

Access-Control-Allow-Credentials: true

浏览器也要允许

var xhr= new XMLHttpRequest();

var url = 'http://bar.other/resources/post-here/';

var body = '<?xml  version="1.0"?>Arun';

function callOtherDomain(){

if(invocation)

{

xhr.withCredentials = true;#允许cookie信息

xhr.open('POST', url, true);

xhr.setRequestHeader('X-PINGOTHER', 'pingpong'); //自定义的Header

xhr.setRequestHeader('Content-Type', 'application/xml'); //特殊的文档类型

xhr.onreadystatechange = function(){};

xhr.send(body);

}

}

服务器设计建议

服务器设计,我们不仅要处理常见的跨域请求,对于Preflighted  Request请求,我们更应该保证浏览器能得到预检请求的结果,因此,服务器端一定要处理OPTIONS请求

来源:oschina

链接:https://my.oschina.net/u/2256215/blog/672556

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值