JS网络请求跨域问题汇总(携带饼干)

前端程序使用ExtJS的写,在本地测试,发送请求到服务器时,发现存在跨域的问题,饼干也没有一套成功,于是乎在这里整理一下解决过程

由于篇幅较长,不想看解决过程的可以翻译到最后看

总结1.跨域允许

2.客户端无法携带跨域cookie

3.因为加了与证件报文头,可能是客户端不知道服务器允许不允许报的错

4.由于客户端不知道服务端是否允许
POST请求而报的错

假设我的服务器IP是120.111.111.123

本地的html

index.html

<html><head> <meta charset="utf8"></head><body> <input type="button" onclick="request()" value="请求"></body><script type="text/javascript" src="./ext-all.js"></script><script type="text/javascript"> function request(){ Ext.Ajax.request({ url: 'http://120.111.111.123/setcookie.php', method: 'POST', params: { 'text': 'hello world' }, success: function(transport){ // do something }, failure: function(transport){ alert("Error: " - transport.responseText); } }); }</script></html>

服务器的php文件#path setcookie.php

<?php
session_start();
?>

点击“请求”按钮,发送请求后发现JS报错

XMLHttpRequest cannot load http://120.111.111.123/setcookie.php.
Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Origin 'null' is therefore not allowed access.

报这个错就说明我们跨域了,不在允许的访问源,于是乎我在服务的setcookie.php加入

header('Access-Control-Allow-Origin:*');
网求允许所有源

<?phpsession_start();header('Access-Control-Allow-Origin:*'); // 功能...// ...

然后又报错

XMLHttpRequest cannot load http://120.111.111.123/setcookie.php. Request header field X-Requested-With is not allowed by Access-Control-Allow-Headers in preflight response.

这次的报错是因为,在跨域的时候,ExtJS的不会直接发帖子请求,而是先发送一个选项请求,看看服务器允许什么访问头(比如是不是允许后请求),验证成功后才会发送真正的请求

用谷歌的开发者工具抓的option报文OPTIONS /setcookie.php HTTP/1.1Host: 120.111.111.123Connection: keep-alivePragma: no-cacheCache-Control: no-cacheAccess-Control-Request-Method: POSTOrigin: nullUser-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36Access-Control-Request-Headers: x-requested-withAccept: /Accept-Encoding: gzip, deflate, sdchAccept-Language: zh-CN,zh;q=0.8

接下来,我们只要发送我们允许什么请求头就行了

path /setcookie.php

session_start();header('Access-Control-Allow-Origin:*');

header('Access-Control-Allow-Methods:OPTIONS, GET, POST'); // 允许option,get,post请求header('Access-Control-Allow-Headers:x-requested-with'); // 允许x-requested-with请求头header('Access-Control-Max-Age:86400'); // 允许访问的有效期

// 功能...// ...

继续测试我们的新功能,成功的解决了跨域问题

1.png

但是,饼干没有“设置成功”。而之所以没有“设置成功”,是因为cookie的存在本地,但是每个饼干都有一个域名,当你本地的饼干中存在你当前访问的域时,才会被带过去,而我的index.html的文件是本地访问的,即

[HTTP://localhost/index.html,而饼干的域是120.111.111.123的,所以不行了于是乎继续改

](http://localhost/index.html%EF%BC%8C%E8%80%8Ccookie%E7%9A%84%E5%9F%9F%E6%98%AF120.111.111.123%E7%9A%84%EF%BC%8C%E6%89%80%E4%BB%A5%E4%B8%8D%E8%A1%8C%E4%BA%86%E3%80%82%E4%BA%8E%E6%98%AF%E4%B9%8E%E7%BB%A7%E7%BB%AD%E6%94%B9)

path index.html

<html>
<head>
<meta charset="utf8">
</head>
<body>
<input type="button" onclick="request()" value="请求">
</body>
<script type="text/javascript" src="./ext-all.js"></script>
<script type="text/javascript"> function request(){
Ext.Ajax.request({
url: 'http://120.111.111.123/setcookie.php',
method: 'POST',
params: {
'text': 'hello world'
},
withCredentials: true, # 加了这个
success: function(transport){
// do something
},
failure: function(transport){
alert("Error: " - transport.responseText);
}
});
}

</script>
</html>

继续访问,报错

XMLHttpRequest cannot load http://120.111.111.123/setcookie.php.
Response to preflight request doesn't pass access control check: A wildcard '*' cannot be used in the 'Access-Control-Allow-Origin' header when the credentials flag is true.
Origin 'null' is therefore not allowed access.
The credentials mode of an XMLHttpRequest is controlled by the withCredentials attribute.

现在这个错误产生的原因就是

1,因为加入了withCredentials之后,访问控制允许来源就不能用“*”了,既然不允许访问这个源,那我就让你发个报文头让你允许
访问呗!

<?php#path setcookie.phpsession_start();// 是否存在请求源if(isset($_SERVER["HTTP_ORIGIN"])) { header('Access-Control-Allow-Origin:'.$_SERVER["HTTP_ORIGIN"]); }header('Access-Control-Allow-Methods:OPTIONS, GET, POST');header('Access-Control-Allow-Headers:x-requested-with');header('Access-Control-Max-Age:86400');// 功能...// ...?>

好了,上传完代码,继续测试。发送请求之后,又报错了(这错中错,一个个坑搞的大家都看得不耐烦了吧,我保证,这是最后一个报错了)

XMLHttpRequest cannot load http://120.111.111.123/setcookie.php.
Response to preflight request doesn't pass access control check: Credentials flag is 'true', but the 'Access-Control-Allow-Credentials' header is ''. It must be 'true' to allow credentials. Origin 'null' is therefore not allowed access.

大概的意思就是说我给你发了withCredentials报文头,但是你服务器没有跟我说允许我带这个报文头,那么解决方法就是加上允许发这个报文头的报文头

path setcookie.php<?phpsession_start();// 是否存在请求源if(isset($_SERVER["HTTP_ORIGIN"])) { header('Access-Control-Allow-Origin:'.$_SERVER["HTTP_ORIGIN"]); }header('Access-Control-Allow-Origin:null'); header('Access-Control-Allow-Methods:OPTIONS, GET, POST');header('Access-Control-Allow-Headers:x-requested-with');header('Access-Control-Max-Age:86400');header('Access-Control-Allow-Credentials:true');// 功能...// ...?>

接下来进行最终的测试,BIU〜成功了,终于成功了!!!(0.0自己嗨起来了)

2.png

接下来总结一下,之所以跨域会引起那么多问题,都是因为耿直的客户端,发什么类型的请求都要服务器允许,而且要明文允许,允许的内容包括如下

1.网求允许跨域

解决方法:服务器发送允许客户端发送源的报文头

标头( '访问控制允许来源:'。$ _ SERVER [ “HTTP_ORIGIN”]);

4.png

2.客户端无法携带跨域cookie的

这个时候就可以在ExtJS的中加入withCredentials

Ext.Ajax.request({ url: 'http://120.111.111.123/setcookie.php', method: 'POST', params: { 'text': 'hello world'
},
withCredentials: true, success: function(transport){ // do something
},
failure: function(transport){
alert("Error: " - transport.responseText);
}
});

3.因为加了withCredentials报文头,可是客户端不知道服务器允不允许报的错
(耿直的客户端)

这个时候就在服务器发送接入控制允许证书

header('Access-Control-Allow-Credentials:true');

4.由于客户端不知道服务端是否允许
POST而请求作者:的错

这个时候要在服务器端的加入

header('Access-Control-Allow-Methods:OPTIONS, GET, POST');header('Access-Control-Allow-Headers:x-requested-with');header('Access-Control-Max-Age:86400');

以上汇总起来就是

header('Access-Control-Allow-Methods:OPTIONS, GET, POST');header('Access-Control-Allow-Headers:x-requested-with');header('Access-Control-Max-Age:86400'); header('Access-Control-Allow-Origin:'.$_SERVER['HTTP_ORIGIN']);header('Access-Control-Allow-Credentials:true');header('Access-Control-Allow-Methods:GET, POST, PUT, DELETE, OPTIONS');header('Access-Control-Allow-Headers:x-requested-with,content-type');header('Access-Control-Allow-Headers:Origin, No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type, X-E4M-With');

代码已经放到

[github上

](https://github.com/HBLong/extjsCorsDemo)了,有啥问题欢迎大家指出

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

推荐阅读更多精彩内容