转载

HTML5跨域开发

HTML5中提供了跨域加载数据的方法,让我们得以从JSONP或者Flash中介等各种绕行方案中解脱出来,更加顺畅地与服务器交流。另一方面,因为PHP是最好的语言……所以在它与Node.js之间,我选择前者作为后端语言开发内容服务。

这篇文章记录使用jQuery+PHP开发跨域应用时的小心得。

身份验证

做身份验证,最简单的办法就是使用PHP的SESSION保存用户信息,于是就要用到Cookie。默认情况下, 跨域Ajax请求发起时候不包含Cookie ,需要我们主动将 XHRwithCredentials 属性设为 true 才行。

jQuery会把 XHR 封装成 jqXHR ,并且不暴露真正的 XHR (说实话这点有点难以理解,尤其是在做上传进度条的时候)。然后它提供一个给真正 XHR 赋值的接口 xhrField ,所以写成代码就是这样事儿的:

$.ajax(url, {   xhrField: {     withCredentials: true   } } 

各种HTTP头

如果不需要验证用户身份,直接在HTTP头中输出 Access-Control-Allow-Origin: * 即可。

我的产品需要验证,那么首先,HTTP头中必须有 Access-Control-Allow-Credentials: true ;此时对域的限制也严格许多,不再允许像前面那样使用 * 放开给任何来源,必须指明哪个具体域可以接受。

关于 Access-Control-Allow-Origin 的值,规范中的说明是“域名列表或null”,然则接下来的“注意”有点诡异:“实际生产中,‘列表或null’要求更严格。你可以认为它实际只允许单一域名或null,而非空格分隔的域名列表。”——既然如此你干脆写个“域名或null”不就完了……

总之对于我们而言,返回的HTTP头中还要包含 Access-Control-Allow-Origin: http://域名 ,指定允许作为来源的协议、域名、端口,并且只能有一个(组)。因为通常来说我们开发环境和生产环境不一样,所以这里的域名最好不要写在服务器配置里;使用PHP,通过 $_SERVER['HTTP_ORIGIN'] 取出访问来源,与白名单比对,通过后再输出相应的头,更加合适。

调试

我选择JSON作为前后端交流的格式。为了方便浏览器解析(也是HTML5的要求),我还返回了 Content-type: application/json 头。

使用PHP少不了使用Xdebug。出现错误时,Xdebug会返回完整的栈,有利排查。但是为了方便阅读,Xdebug还会给返回信息套上 <table> 结构,这时Chrome的Network工具就会把它解析成奇怪的格式,所以 Content-type 一定要最后和数据一起返回。

与之相反的是前文说到的 Access-Control-Allow-OriginAccess-Control-Allow-Credentials ,这二位必须放在最前面。不然如果出现错,响应头不包含这两个跨域标记,Chrome就会理所当然地不显示返回内容,也就无法看到错误描述,根本无法排查。

参考资料

  1. Using CORS
  2. Cross-Origin Resource Sharing
  3. HTTP access control (CORS)
  4. jQuery.ajax()

分享到

  • 新浪微博
  • 腾讯微博
  • 豆瓣
  • QQ空间

相关

正文到此结束
Loading...