使用HTML5 CORS特性进行Ajax跨域POST请求

跨域一直以来都是个非常神奇,又非常普遍的问题。出于安全等因素的考虑,通常情况下,浏览器通常会仅限制资源的访问,XHR(Ajax)的跨域请求是不被允许的。

但跨域的需求却一直都在,为了跨域,勤劳勇敢的程序猿们想出了许许多多的方法,例如,jsonP、代理文件等等。但这些做法增加了许多不必要的维护成本,而且应用场景也有许多限制,例如jsonP并非XHR,所以jsonP只能使用GET传递参数。

在移动应用风生水起的如今,托HTML5的福,Mobile Web,甚至Hybird App也逐渐火起来,在本地文件系统的Web页面,也有需要获取外部数据的需求,而这些需求也必然是跨域的。同时,HTML5也来带了叫“Cross-Origin Resource Sharing”的新特性,来赋予开发者权力决定资源是否允许被跨域访问。

Access-Control-Allow-Origin
CORS通过服务器增加一个特殊的Header[Access-Control-Allow-Origin]来告知客户端跨域的限制,如果浏览器支持CORS的话,如果判断Origin通过的话,就会允许XHR进行请求,而不需要再使用jsonP或者代理文件。

使用这个Header返回被允许请求跨域请求的来源域,例如网站duelist.cn设置了下面的Header
Access-Control-Allow-Origin: http://smdcn.net
这样设置之后,通过http://smdcn.net下的页面对于duelist.cn进行ajax请求就会被允许,而其他网站对duelist.cn依旧会被阻拦,通过这种方式网站拥有者可以自己对此进行限制。

当然,如果不想限制来源,可以通过
Access-Control-Allow-Origin: *
来允许任何站点对该资源进行跨域请求


关于CORS的浏览器支持情况(caniuse cors):
Can I use CORS
* 主流的移动浏览器:√

如果想要需要对于IE8和9支持CORS:可以使用jquery.iecors


设置CORS
对于客户端来说,一般来说不需要进行额外的设置,只要保证浏览器支持CORS即可
对于服务端,需要给支持CORS的资源增加Access-Control-Allow-Origin的Header。
可以通过HTTP服务器进行统一的Header设置,如果执行的是程序脚本,也可以在程序脚本中加入。
例如,PHP的话,使用

Header(“Access-Control-Allow-Origin:*”);

更多关于CORS的使用参考:http://enable-cors.org/


关于Android浏览器的注意事项
在某些版本的Android浏览器中,因为缓存的原因,第一次进行CORS是正常的,但是第二次进行的时候则会失效,对于这个问题,可以通过在Header中增加Cache-Control: no-cache 阻止缓存的方式来解决这个问题


关于跨域请求读取Cookie的需求
CORS的跨域请求默认情况下不发送本地cookie,同时也不接受来自服务器的cookie。
在跨域请求中读写Cookie并不被推荐,但是如果非要使用Cookie的话,需要在服务端返回是增加Header:

Access-Control-Allow-Credentials:true

同时ajax请求时,对XMLHttpRequest对象设置withCredentials = true;

var xhr = new XMLHttpRequest();
xhr.open();
xhr.withCredentials = true;

在Android WebView中使用HTML5的video标签播放本地视频

因为毕设需要,这段时间就一直在做基于HTML5 video定制的播放器,因为开发和测试过程也一直都是配合Nexus7的Chrome进行测试,所以本以为Android上应该会是最为顺利没有问题的,但是在经过PhoneGap封装测试时,发现在iOS上完全正常,但是在Android上反而没办法播放了。

问题出现在用Android的Webview在播放应用assets中视频的时候,但我尝试把视频地址改为互联网地址的时候就正常了。

经过反复测试,发现使用HTML5访问应用资源目录的时候会存在Android权限限制的问题,不过访问sdcard是能够正常使用的,也就是地址是:file://sdcard/ 下的就可以正常使用了。(对于远程文件下载到本地后播放直接下载到sdcard自己的目录即可;如果原先视频文件已经在assets目录的,则可以在启动WebView前复制到sdcard)

上述测试的环境为 Nexus 7 (with Android 4.4.2) / Android 4.4 SDK

PS:

网络上还有说HTML5播放视频需要在AndroidManifest.xml开启硬件加速

<application android:hardwareAccelerated="true"

我用PhoneGap的时候默认生成的就已经是开启的了,就没作另外的测试。