We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
如今使用 CORS 技术做跨域通信已经不是什么新鲜事情了,我们网页中的很多接口在跨域方案上也首选 CORS。然而 CORS 看似完美的背后,却有值得我们注意的地方。
我们团队在开发新需求的时候,测试 MM 发现 IE8 下网页中的一个 CORS 接口返回异常,提示没有权限,排查这个问题的过程中加深了我们对 IE 实现 CORS 技术的认知。
网上已经有太多的篇幅描述 CORS 是什么,这里简单介绍一下。CORS 技术就是为了实现跨域请求,而在响应头中设置一些 CORS 技术规定的响应头,如 Access-Control-Allow-Origin 等用以实现客户端与服务端进行跨域通信。
Access-Control-Allow-Origin
通常一个简单的 CORS 响应头组成有如下内容:
Access-Control-Allow-Methods: POST, GET, OPTIONS Access-Control-Allow-Origin: http://www.yixun.com
CORS 方案的 HTTP 请求是不会携带 cookie 的,如果需要带上 cookie,需要在响应头中多添加一些字段:
Access-Control-Allow-Credentials:true Access-Control-Allow-Headers:withCredentials
同时客户端在请求头中需要设置字段 withCredentials 为 true。
withCredentials
true
withCredentials: true
允许带 cookie 时,Access-Control-Allow-Origin 字段值不可以设置为 *。
*
CORS 方案较之于传统的方案优点很多。
document.domain
iframe
window.postMessage
总结下来,选择 CORS 跨域方案最大的好处是返回数据可以在跨域与同域时完美兼容,不需要接口多 处理不同情况下的返回数据格式,前端实现也十分简单方便。
返回文章起首提到的问题,请求接口提示没有权限。但是在 Chrome、Firefox 中确认接口是正确添加了 CORS 需要的响应头字段了。
后来在爆栈上搜索发现,原来 IE8\9 实现 CORS 的对象和实现 AJAX 的对象(XMLHTTP)不是同一个,而是使用了 window.XDomainRequest 对象。
XMLHTTP
window.XDomainRequest
由于我们的 PC 站使用的 jQuery 版本太低(5.1版),$.ajax 方法没有兼容 IE8\9 的 XDomainRequest 对象,于是网页使用了 XMLHTTP 对接口发起请求,所以会返回“没有权限”的提示。为了兼容这个情况,我们做了一些手动的兼容:
$.ajax
XDomainRequest
if (/*判断是否跨域*/ && window.XDomainRequest) { var xdr = new XDomainRequest() xdr.open('post', url) xdr.onload = function() { //success(xdr.responseText); } xdr.send() } else { $.ajax(...) }
在 IE8/9 下使用 XDomainRequest 进行跨域时还有一些限制:
在有上述两项需求并需要兼容 IE8\9 时,CORS 方案就无法满足我们的需求了,需要定制另外的跨域方案。于是我们有部分接口只能通过修改接口将需要的 cookie 值放在请求的 query string 中或者采用其他的跨域方案解决问题。
当仅二级域名不同时,通过两个页面设置相同的主域名,比如
//base.yixun.com document.domain = 'yixun.com'
就可以互相通信。接口可以通过 form 元素的 target 属性指定提交至一个 iframe 元素中,接口中返回带有格式的数据,如:
form
target
<!--接口的返回数据--> <script> document.domain = 'yixun.com' frameElement.callback(...) // frameElement 即 iframe 元素本身,callback 方法在父页面中定义 </script>
iframe 元素得到了一个 script 标签并执行,而 iframe 元素的 callback 预先已经定义好:
script
callback
ifr = document.getElementById(...) //获取 iframe 元素 ifr.callback = function (d) { //定义 iframe 元素的 callback 方法 success(d) this.src = 'about:blank' //避免页面刷新重复提交 }
postMessage 方案和 document.domain 原理相似,就不再赘述。
postMessage
The text was updated successfully, but these errors were encountered:
No branches or pull requests
关于 CORS —— 小船翻在了 IE8 的小沟沟里
如今使用 CORS 技术做跨域通信已经不是什么新鲜事情了,我们网页中的很多接口在跨域方案上也首选 CORS。然而 CORS 看似完美的背后,却有值得我们注意的地方。
我们团队在开发新需求的时候,测试 MM 发现 IE8 下网页中的一个 CORS 接口返回异常,提示没有权限,排查这个问题的过程中加深了我们对 IE 实现 CORS 技术的认知。
## CORS 是什么
网上已经有太多的篇幅描述 CORS 是什么,这里简单介绍一下。CORS 技术就是为了实现跨域请求,而在响应头中设置一些 CORS 技术规定的响应头,如
Access-Control-Allow-Origin
等用以实现客户端与服务端进行跨域通信。通常一个简单的 CORS 响应头组成有如下内容:
CORS 方案的 HTTP 请求是不会携带 cookie 的,如果需要带上 cookie,需要在响应头中多添加一些字段:
同时客户端在请求头中需要设置字段
withCredentials
为true
。允许带 cookie 时,
Access-Control-Allow-Origin
字段值不可以设置为*
。## 为什么选择 CORS 方案
CORS 方案较之于传统的方案优点很多。
document.domain
方案,CORS 方案的响应内容没有格式限制,而document.domain
方案不仅需要设置document.domain
,还需要借助iframe
元素接受带有指定格式的返回数据,方案比较繁琐;window.postMessage
方案和上述的document.domain
方案基本类似,不仅需要对接口的返回数据进行特别处理,还需要使用一个iframe
元素进行接受。总结下来,选择 CORS 跨域方案最大的好处是返回数据可以在跨域与同域时完美兼容,不需要接口多
处理不同情况下的返回数据格式,前端实现也十分简单方便。
## IE8 下为什么请求提示没有权限?
返回文章起首提到的问题,请求接口提示没有权限。但是在 Chrome、Firefox 中确认接口是正确添加了 CORS 需要的响应头字段了。
后来在爆栈上搜索发现,原来 IE8\9 实现 CORS 的对象和实现 AJAX 的对象(
XMLHTTP
)不是同一个,而是使用了window.XDomainRequest
对象。由于我们的 PC 站使用的 jQuery 版本太低(5.1版),
$.ajax
方法没有兼容 IE8\9 的XDomainRequest
对象,于是网页使用了XMLHTTP
对接口发起请求,所以会返回“没有权限”的提示。为了兼容这个情况,我们做了一些手动的兼容:在 IE8/9 下使用
XDomainRequest
进行跨域时还有一些限制:在有上述两项需求并需要兼容 IE8\9 时,CORS 方案就无法满足我们的需求了,需要定制另外的跨域方案。于是我们有部分接口只能通过修改接口将需要的 cookie 值放在请求的 query string 中或者采用其他的跨域方案解决问题。
## 扩展阅读 ### document.domain 跨域方案
当仅二级域名不同时,通过两个页面设置相同的主域名,比如
就可以互相通信。接口可以通过
form
元素的target
属性指定提交至一个iframe
元素中,接口中返回带有格式的数据,如:iframe
元素得到了一个script
标签并执行,而iframe
元素的callback
预先已经定义好:postMessage
方案和document.domain
原理相似,就不再赘述。## Thanks
The text was updated successfully, but these errors were encountered: