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? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in 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: