ajax跨域实战
需求来源
用node、python、nginx实现http代理服务器中遇到的问题
防跨域的安全
广告或恶性脚本,不能背着你,偷偷把数据传其他服务器去
跨域的涵义
协议://主机:端口,三者任一不同则为跨域。
其中协议有file,http,https,smtp,ftp等,
主机则有域名(www.baidu.com)、IP(127.0.0.1)两种,
端口http默认80,https默认443。
jquery-1.12.3.js第9618行源码展示了这一点
// A cross-domain request is in order when we have a protocol:host:port mismatch
if ( s.crossDomain == null ) {
parts = rurl.exec( s.url.toLowerCase() );//分析url出 协议:主机:端口
s.crossDomain = !!( parts &&
( parts[ 1 ] !== ajaxLocParts[ 1 ] || parts[ 2 ] !== ajaxLocParts[ 2 ] ||
( parts[ 3 ] || ( parts[ 1 ] === "http:" ? "80" : "443" ) ) !==
( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? "80" : "443" ) ) )
);
//判断是否任一相同,对默认的http80和https443判断
}
浏览器设置
chrome浏览器不允许从file://发起ajax,需要在浏览器快捷方式-属性-目标后加上 --allow-file-access-from-files
不加上这个,http的request报文内Origin为null,加上后为file://
http报文交互
request | response
Origin:file:// | Access-Control-Allow-Origin:*
reponse报头Access-Control-Allow-Origin是对request报头Origin的回应,若为*表示全部都同意,也可为固定的协议和域名来限定允许跨域的范围,若对应不上,浏览器则认为服务器不允许跨域,报错
request | response
Origin:http://127.0.0.1:80 | Access-Control-Allow-Origin:http://127.0.0.1:80
| Access-Control-Allow-Credentails:true
reponse报头Access-Control-Allow-Credentails标示可以上传cookie来保持session会话,但Access-Control-Allow-Origin就不能设为*了,需要指定
request | response
Accept:text/html,*/*;q=0.01 | Content-Type:text/html;charset=utf-8
reponse报头Content-Type标示返回的数据格式,对应request的Accept报头,若不匹配,浏览器会认为格式不正确,而报转换异常
非简单请求
request | response
myhead:a | Access-Control-Allow-Headers:myhead
| Access-Control-Allow-Methods:POST,GET,OPTIONS
当带有自定义head时,jquery的ajax会先调OPTIONS方法,判断当前的GET或POST方法服务器是否允许,减少通信量
iframe跨域
| response
| X-Frame-Options:SAMEORIGIN
reponse报头X-Frame-Options有三个值
DENY 表示页面不允许在iframe中展示,相同域名也不可以
SAMEORIGIN 表示页面可以在相同域名页面的frame中展示
ALLOW-FROM uri 表示指定iframe中展示
jsonp
通过js下载执行方法避开跨域,但只能用于GET,传统的方法,不易定制