跨域post请求

跨域post请

今天被布置了一个任务,要ajax跨域做一个post请求,叫我去查查要怎么实现。

出于安全方面的考虑,ajax是不给跨域的(这里指的ajax其实是浏览器的对象XMLHttpRequest()),除非要有服务器端代理,意思是同域下的服务器提供服务帮我们做一个中转。可以看到,我们请求的其实仍然是同域的服务器,事实上并没有绕开跨域的问题,而是将它抛给服务器端解决,缺点也很明显,必须服务器提供一个服务,而且数据多走了一个来回,效率就变得比较低了,好处是不会有兼容性的问题。我想要一个纯前端的方案,所以server proxy排除。

这里觉得要提一下,看网上很多关于ajax的文章,其中ajax指的并不是浏览器的那个对象,而是指一种不用刷新页面就更新数据的手段,总会提jasonpm,iframe之类的,其实严格来说这些和ajax一点关系都没有,这是一个概念上的不同吧。

那我们抛开ajax来看,其实需求就是要达到不刷新页面的效果,不用ajax,跨域的解决方案其实挺多,jasonp算一个,但只能用get方法,post就无能为力了。get的数据是存放在url中的,如果数据量太大就不能支持了,而且从安全方面考虑也差一点,排除。关于jasonp之前写过一篇文章,有兴趣的戳传送门

flash也是可以post到任何域,原理是flash自己有一个跨域标准,在服务器要有一个文件定义允许跨域访问的域名。flash如果读到这个文件,并且允许当前域名访问,就可以进行跨域了。但是flash的方式需要安装插件,而且我不喜欢flash,所以也排除。

最后看来有两种解决方法,一种是CORS,一种是iframe+form,前者高大上,后者相对比较麻烦,但兼容性较好,下面分别来说一下。

CORS

CROS是Cross-Origin Resource Sharing的缩写,一看就知道是用来解决跨域问题的,其实这是通过在响应中加入允许跨域访问的头信息来实现的,标准比较新,所以并不是所有的浏览器都实现了。下面的图是从caniuse.com截的图。

这样看来兼容性也不算太差,自己做小项目可以玩玩,移动端的除了Opera,主流的也都可以。

详细的标准可以上w3.org看看,英文苦手的话还是搜一下Cross-Origin Resource Sharing协议,看看博客一般也够了。我自己也不喜欢看英文,但慢慢觉得想要研究什么东西的话,还是得耐下性子看文档。

响应头有以下6个

1.Access-Control-Allow-Origin

取值可以是”origin-list-or-null | *”,但文档中也说,实现的时候和标准有区别,并不支持list的形式,后面测试的时候来试试。

2.Access-Control-Allow-Credentials

credentials是凭证的意思,是预检请求才会用到的一个属性,放在后面一起讲

3.Access-Control-Expose-Headers

这个头规定哪些头可以暴露给CROS API规范的API

4.Access-Control-Max-Age

规定那些预检请求验证通过的信息可以缓存多久

5.Access-Control-Allow-Methods

响应预检请求,指定在通过预检之后真正的跨域请求中,哪些method是可用的。

6.Access-Control-Allow-Headers

响应预检请求,指定在通过预检之后真正的跨域请求中,哪些头是可用的。

请求头有3个

1.Origin

该字段表明跨域请求的来源

2.Access-Control-Request-Method

预检请求的字段,指明在真正的跨域请求中,要用哪种方法

3.Access-Control-Request-Headers

预检请求的字段,指明在真正的跨域请求中,要用哪个字段

这里看到预检请求,真正的跨域请求等名词,都是什么意思呢。其实CORS跨域请求有两种,一种是简单的,一种是预检的。

简单的CORS跨域请求就是简单的跨域GET或者POST,然后外域服务器端给你返回一个带有Access-Control-Allow-Origin: “当前域” 头信息的响应,就表明他允许你的跨域请求了。

预检的CORS跨域请求就是说,要先发一个OPTION请求,告诉外域的服务器你要带什么头信息,用什么方法等等,问他肯不肯,这个请求就是所谓的预检请求。等外域的服务器允许了你的预检请求,后面才会发起真正的跨域请求。

我们分别来对着两种CORS跨域请求做下测试

一,简单的CORS跨域请求

两台机子,各开一个web服务器,我这里用的都是node。A机地址是192.168.1.104,B机器的地址是192.168.1.100.

A机器上服务的页面代码如下

B机器是一个测试机,我们来看看结果(公司机器,打个码)

可以看到post的请求成功了,服务器的响应也拿到了,但是响应内容log出来却出错了

由于同源策略,iframe之间不能相互访问,我们并不能直接得到这个POST的响应的内容。

做到这里,只能大喊一声妈蛋,搞这么多还是拿不到数据,有个屁用啊。

其实还是有办法的,至少请求已经成功,而且数据也到了本地,我们可以通过浏览器窗口之间的postMessage来传递,仍然需要服务器端的配合,我们请求B站返回数据的时候,B站不能直接返回一个数据就完事儿了,而是要用postMessage把数据给丢出来

A站页面的js修改如下


iframe.onload = function () {
    window.frames[0].postMessage("testtest","http://xxxxxxxxxx:8888/");
}
window.addEventListener("message", function(event){
    console.log(event.data);
}, false);

然后终于,在控制台上看到了输出

我们来看看postMessage的支持情况

情况比CORS好一些,但要兼容IE6和7之类的,估计就只能用flash了。

参考资料
http://www.w3.org/TR/cors/

http://www.cnblogs.com/shanyou/archive/2012/09/16/2687907.html

http://www.iteye.com/topic/600682
http://blog.sina.com.cn/s/blog_6940cab30101a1yj.html
http://stackoverflow.com/questions/298745/how-do-i-send-a-cross-domain-post-request-via-javascript#answer-6169703

你可能感兴趣的:(webMethods)