XMLHttpRequest的跨域请求

XMLHttpRequest的跨域请求

动态添加一个标签,而script标签的src属性是没有跨域的限制的。这样说来,这种跨域方式其实与ajax XmlHttpRequest协议无关了。

这样其实"jQuery AJAX跨域问题"就成了个伪命题,jquery $.ajax方法名有误导人之嫌。

如果设为dataType: 'jsonp',这个$.ajax方法就和ajax XmlHttpRequest没什么关系了,取而代之的则是JSONP协议。JSONP是一个非官方的协议,它允许在服务器端集成Script tags返回至客户端,通过javascript callback的形式实现跨域访问。

JSONP即JSON with Padding。由于同源策略的限制,XmlHttpRequest只允许请求当前源(域名、协议、端口)的资源。如果要进行跨域请求, 我们可以通过使用html的script标记来进行跨域请求,并在响应中返回要执行的script代码,其中可以直接使用JSON传递 javascript对象。 这种跨域的通讯方式称为JSONP。

Cross-Origin Resource sharing

这是W3C  新出的一个标准,简单的讲就是通过服务器/客户端 一些Headers的设置及确认 来实现跨域请求,这些包头有

Cross-Origin Resource sharing

这是W3C  新出的一个标准,简单的讲就是通过服务器/客户端 一些Headers的设置及确认 来实现跨域请求,这些包头有

Syntax

5.1Access-Control-Allow-OriginResponse Header

5.2Access-Control-Allow-CredentialsResponse Header

5.3Access-Control-Expose-HeadersResponse Header

5.4Access-Control-Max-AgeResponse Header

5.5Access-Control-Allow-MethodsResponse Header

5.6Access-Control-Allow-HeadersResponse Header

5.7OriginRequest Header

5.8Access-Control-Request-MethodRequest Header

5.9Access-Control-Request-HeadersRequest Header

例如

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

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

Access-Control-Allow-Headers: POWERED-BY-MENGXIANHUI

Access-Control-Max-Age: 30

可以参考 http://www.w3.org/TR/access-control/#access-control-allow-origin-response-header  w3c的网站

1

2

3

4

5

6

7Access-Control-Allow-Origin: 允许跨域访问的域,可以是一个域的列表,也可以是通配符"*"。这里要注意Origin规则只对域名有效,并不会对子目录有效。

即http://www.test/test/是无效的。但是不同子域名需要分开设置,这里的规则可以参照那篇同源策略

Access-Control-Allow-Credentials: 是否允许请求带有验证信息,这部分将会在下面详细解释

Access-Control-Expose-Headers: 允许脚本访问的返回头,请求成功后,脚本可以在XMLHttpRequest中访问这些头的信息(貌似webkit没有实现这个)

Access-Control-Max-Age: 缓存此次请求的秒数。在这个时间范围内,所有同类型的请求都将不再发送预检请求而是直接使用此次返回的头作为判断依据,非常有用,大幅优化请求次数

Access-Control-Allow-Methods: 允许使用的请求方法,以逗号隔开

Access-Control-Allow-Headers: 允许自定义的头部,以逗号隔开,大小写不敏感

Access-Control-Allow-Credentials

在跨域请求中,默认情况下,HTTP Authentication信息,Cookie头以及用户的SSL证书无论在预检请求中或是在实际请求都是不会被发送的。

但是,通过设置XMLHttpRequest的credentials为true,就会启用认证信息机制。

虽然简单请求还是不需要发送预检请求,但是此时判断请求是否成功需要额外判断Access-Control-Allow-Credentials,如果Access-Control-Allow-Credentials为false,请求失败。

十分需要注意的的一点就是此时Access-Control-Allow-Origin不能为通配符"*"(真是便宜了一帮偷懒的程序员),如果Access-Control-Allow-Origin是通配符"*"的话,仍将认为请求失败

即便是失败的请求,如果返回头中有Set-Cookie的头,浏览器还是会照常设置Cookie

客户端页面test.php

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

crossDomainRequest

functioncreateXHR(){

returnwindow.XMLHttpRequest?

newXMLHttpRequest():

newActiveXObject("Microsoft.XMLHTTP");

}

functiongetappkey(url){

xmlHttp = createXHR();

xmlHttp.open("GET",url,false);

xmlHttp.send();

result = xmlHttp.responseText;

returnresult;

}

functioncrossDomainRequest(){

varcontent =getappkey('http://127.0.0.10/gettest.php');

document.getElementById("content").innerHTML=content;

}

服务端页面gettest.php

1

2

3

4

header("Access-Control-Allow-Origin:  http://127.0.0.1");

echo"test success!";

?>

如果不允许的话

所以跨域有以下几种方法

通过webserver【nginx】配置来跨域

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36#

# Wide-open CORS config for nginx

#

location / {

if($request_method ='OPTIONS') {

add_header'Access-Control-Allow-Origin''*';

#

# Om nom nom cookies

#

add_header'Access-Control-Allow-Credentials''true';

add_header'Access-Control-Allow-Methods''GET, POST, OPTIONS';

#

# Custom headers and headers various browsers *should* be OK with but aren't

#

add_header'Access-Control-Allow-Headers''DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';

#

# Tell client that this pre-flight info is valid for 20 days

#

add_header'Access-Control-Max-Age'1728000;

add_header'Content-Type''text/plain charset=UTF-8';

add_header'Content-Length'0;

return204;

}

if($request_method ='POST') {

add_header'Access-Control-Allow-Origin''*';

add_header'Access-Control-Allow-Credentials''true';

add_header'Access-Control-Allow-Methods''GET, POST, OPTIONS';

add_header'Access-Control-Allow-Headers''DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';

}

if($request_method ='GET') {

add_header'Access-Control-Allow-Origin''*';

add_header'Access-Control-Allow-Credentials''true';

add_header'Access-Control-Allow-Methods''GET, POST, OPTIONS';

add_header'Access-Control-Allow-Headers''DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';

}

}

示例代码

1

2

3

4

5

6

7

8

9

10location /{

add_header'Access-Control-Allow-Origin''http://www.test.com';

add_header'Access-Control-Allow-Credentials''true';

add_header'Access-Control-Allow-Methods''GET';

...

...

}

第一条指令:授权从http://www.test.com的请求

第二条指令:当该标志为真时,响应于该请求是否可以被暴露

第三天指令:指定请求的方法,可以是GET,POST等

如果需要允许来自任何域的访问,可以这样配置

1

Access-Control-Allow-Origin: *

通过后端程序来跨域

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

header("Access-Control-Allow-Origin:http://www.test.com");

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

echojson_encode($_POST);

?>

$("#ajax").click(function(){

$.ajax({

type:"POST",

url:"http://www.test.com/test2.php",

data:'name=test',

dataType:"json",

success:function(data){

$('#Result').text(data.name);

}

});

});

JSONP

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

if(isset($_GET['name']) && isset($_GET['callback']))

//callback根js端要对应,不然会报错的

{

echo$_GET['callback'].'('. json_encode($_GET) . ');

}

?>

$("#jsonp").click(function(){

$.ajax({

url:'http://www.test.com/test1.php',

data: {name:'jsonp'},

dataType:'jsonp',

jsonp:'callback',//为服务端准备的参数

jsonpCallback:'getdata',//回调函数

success:function(){

alert("success");

}

});

});

functiongetdata(data){

$('#Result').text(data.name);

}

getJSON

1

2

3

4

5

6

7

8

$("#getjson").click(function(){

$.getJSON('http://www.test.com/test1.php?name=getjson&callback=?',function(data){

//没有回调函数,直接处理

$('#Result').text(data.name);

})

})

getScript

1

2

3

4

5

$("#getscript").click(function(){

$.getScript('http://www.test.com/test1.php?name=getscript&callback=getdata');

});

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,968评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,601评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,220评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,416评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,425评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,144评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,432评论 3 401
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,088评论 0 261
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,586评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,028评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,137评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,783评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,343评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,333评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,559评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,595评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,901评论 2 345

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,601评论 18 139
  • 前言:对于跨域请求,很早之前就有去了解过,但因为一直关注的都是服务器后端开发,故也就仅仅停留在概念的理解上而没有机...
    ken_ljq阅读 89,722评论 6 128
  • 1. 所谓跨域 跨域是一种浏览器同源安全策略,也即浏览器单方面限制脚本的跨域访问。很多人可能误认为资源跨域时无法请...
    blurooo阅读 6,157评论 11 54
  • 同源策略 理解跨域首先必须要了解同源策略。同源策略是浏览器上为安全性考虑实施的非常重要的安全策略。何谓同源:URL...
    48892085f47c阅读 716评论 0 6
  • 前端程序使用ExtJS的写,在本地测试,发送请求到服务器时,发现存在跨域的问题,饼干也没有一套成功,于是乎在这里整...
    南滨月亮阅读 1,493评论 0 1