美文网首页
跨域(Cross-Domain)之痛

跨域(Cross-Domain)之痛

作者: NoteCode | 来源:发表于2016-07-20 20:54 被阅读315次

我们只想做一个安分的软件“工程师”,只想专注于业务逻辑(因为老板只盯着他所关注的功能、版本、优化),不立志成为计算机“科学家”,解决那些底层的、不兼容、各种奇葩的实现(因为老板不觉得自己应该给这些“科研”工作出经费)。于是,从一开始,我们就本着“只要实现功能就行”的不科学态度,在基础知识上没有系统学习过……直到几次让人非常沮丧、非常被动的情况发生,我们才不得不审视一直以来的“短视”。

跨域(Cross-Domain)之痛(二)

jsonp存在的问题

硬问题:
  1. 不支持POST方法
    jsonp基于GET方法实现,并没有用XMLHttpRequest,不是真正的ajax请求。所以,仅有jsonp是不够的,服务端无论如何都免不了支持CORS。
  2. 欲捕获服务端返回的500等错误,捕获不到。jquery有文档明确说明:(function error) This handler is not called for cross-domain script and cross-domain JSONP requests. 我还不甚了了why
软问题:

服务端需要支持两种方式,而这种机制性的代码又不常改(除非出问题)。平时前端、后端都专注业务逻辑,前端没毛病,后端同学是万万不会想到这个代码。某一天,前端发现了问题,思量 “记得xx点原来是可以的啊,怎么今天不行了……”,又是一番google,一番尝试,结果发现:哦,原来是jsonp可以,json不行(要么就是json可以,jsonp不行)。这就是记忆的局限。毕竟,看不到对方代码,记忆中是支持的,却常常忽略了“两种方式”这件事。


注意:下面说的都是弃用jsonp后遇到的问题

ajax带不上cookie

这样子做:

1) Add the following to your ajax request.
xhrFields: { withCredentials:true }

2) Add the following to your response headers for resources in the different subdomain.
Access-Control-Allow-Origin : http://original.mydomain.com
Access-Control-Allow-Credentials : true

The XMLHttpRequest.withCredentials property is a Boolean that indicates whether or not cross-site Access-Control requests should be made using credentials such as cookies, authorization headers or TLS client certificates. Setting withCredentials has no effect on same-site requests.

详见 StackOverflow

IE8/IE9不支持ajax

我一直以为XMLHttpRequest是浏览器的标配,事实告诉我,真是没见过世面!人家伟大的IE8/IE9就不标配,有自己的XDomainRequest

幸好,有人为jquery写了插件jQuery-ajaxTransport-XDomainRequest。在引入jquery.js之后引入它,$.ajax的地方不用改,齐活。

强调一下,如果你引入了插件,发现仍然是返回500错误,请确认返回头中有Access-Control-Allow-Origin

CORS requires the Access-Control-Allow-Origin header to be present in the AJAX response from the server.

我在这里费了好半天劲。因在我的印象中,我们一直是返回这个header的,否则在chrome、safari上早该有问题了。所以,在我读插件的文档时看到这句话,很自信地认为“恩,这步我们已经有了”。当我怀疑是插件没加载成、没执行、插件不靠谱等等各种尝试后,有点灰心的时候,不经意发现,返回的header中真的是没有Access-Control-Allow-Origin。为何呢?明明是服务端已加了的啊。

去查一下php代码,发现我们是从请求header中的Referer中取出http://domain.com:port/ 来生成Access-Control-Allow-Origin(没有Referer则没办法生成)。可现在IE的请求中没有Referer,倒是有个Origin。再去查查标准文档 w2c,才知道,原来Origin才是正确的姿势。

改了php代码,世界安静了。

后来,我终于在眼泪中明白,有些软件,总那么不可爱

然而,IE8/IE9问题只是“貌似”解决了。当时应该也是没有全面测试,后来发现,登录不了。原来是带不上Cookie!也就是说,XDomainRequest实现的有局限。参见:微软某程序员的一篇blog

看来,如果需要兼容IE8,是不能完美实现CORS的。

最终的最终,我们还是无奈地选择了“js中访问同域名下的php,nginx做代理(将请求转发给api)”这种方式。

refs:
http://stackoverflow.com/questions/2870371/why-is-jquerys-ajax-method-not-sending-my-session-cookie
http://www.w3.org/TR/cors/
https://en.wikipedia.org/wiki/Cross-origin_resource_sharing
http://bob.ippoli.to/archives/2005/12/05/remote-json-jsonp/
https://en.wikipedia.org/wiki/JSONP

相关文章

  • 跨域(Cross-Domain)之痛(二)

    第二波兼容IE8(IE9同)的工作,搞了半天,又是跨域导致 跨域(Cross-Domain)之痛 bootstra...

  • 跨域(Cross-Domain)之痛

    我们只想做一个安分的软件“工程师”,只想专注于业务逻辑(因为老板只盯着他所关注的功能、版本、优化),不立志成为计算...

  • 浅谈跨域问题的出现及其解决方案

    项目源码:https://github.com/trp1119/cross-domain 1 跨域问题的出现 1....

  • 学习记录000之跨域&&Token&&a

    学习记录000之跨域&&Token&&Restful设计 1.跨域 1.1什么是跨域 一张图来了解下哪些情况下存在...

  • jsonp跨域

    什么是跨域 请求协议(http,https)不同 域名(domain)不同 端口(port)不同 跨域解决方案之 ...

  • 深入跨域问题(3) - 利用 JSONP 解决跨域

    深入跨域问题(1) - 初识 CORS 跨域资源共享;深入跨域问题(2) - 利用 CORS 解决跨域深入跨域问题...

  • 关于设置env等环境变量的思考

    1、如何处理跨域后台处理跨域前端处理跨域浏览器处理跨域 前端本地处理跨域:代理线上跨域的处理方式:Nginx反向代...

  • Web前后端跨域问题处理

    跨域问题有前台跨域(iframe间)和后台跨域。 前台跨域的解决方案可以采用跨域文档通讯(Cross domain...

  • 跨域

    跨域 什么是跨域: 解决跨域 通过jsonp原理:在页面引入跨域js和css时,没有存在跨域问题.因此可以动态创建...

  • 跨域问题详解分析

    参考文档 CORS详解 跨域资源共享 CORS 详解 js中几种实用的跨域方法原理详解 跨域的那些事儿 跨域与跨域...

网友评论

      本文标题:跨域(Cross-Domain)之痛

      本文链接:https://www.haomeiwen.com/subject/oovvjttx.html