IE6/7 ajax跨域设置

经实测,IE6、IE8打开跨域站点,则抛出异常

var xhr = new ActiveXObject(‘Microsoft.XMLHTTP‘);
xhr.open(‘GET’, url, true); // throw a denie access error

打开IE工具-Internet选项-设置-安全,把页面所在的网站,加入到可信站点或者本地Intranet,就不会抛出异常了,url就可以是任何网站了!

实际使用时,可信站点 和 本地Intranet还是有区别的。自定义级别-其他-通过域访问数据源,这个选项不一样,本地Intranet是提示,会提示你:

该页正在访问其控制范围之外的信息。这有些危险。是否继续?

如果点击是,则出现正常结果,点击否那么又抛异常。

非常诡异的事情是:在IE6下,把页面所在的网站,加入到本地Intranet,而需要open的url加入到可信站点,就坏了,就坏了,就坏了!而两者都在本地Intranet却是预期结果,有提示。

在IE8下,把页面所在的网站,加入到本地Intranet,而需要open的url加入到可信站点,也是坏的。不过IE8的可信站点级别是中级,还说的过去。

IE6下面,可信站点的级别是低,而本地Intranet级别是中低,他们哪里肯定还有不一样。

为了不影响测试,我把本地Intranet里面的三个勾都去掉了。勾上其中某几个的话,会把原本没加进本地Intranet的站点,算成是本地Intranet的。而默认是勾上的。

结论:
IE6下,不能把要open的url加入到可信站点;把页面所在的网站,加入到可信站点。
IE8下,也是不能把要open的url加入到可信站点;但页面所在的网站,是加入到本地Intranet。

 

IE7没试过。以后有条件再试。

how to I access XHR responseBody (for binary data) in IE

http://stackoverflow.com/questions/1919972/how-do-i-access-xhr-responsebody-for-binary-data-from-javascript-in-ie

I’ve got a web page that uses XMLHttpRequest to download a binary resource.

In Firefox and Gecko I can use responseText to get the bytes, even if the bytestream includes binary zeroes. I may need to coerce the mimetype with overrideMimeType() to make that happen. In IE, though, responseText doesn’t work, because it appears to terminate at the first zero. If you read 100,000 bytes, and byte 7 is a binary zero, you will be able to access only 7 bytes. IE’s XMLHttpRequest exposes a responseBody property to access the bytes. I’ve seen a few posts suggesting that it’s impossible to access this property in any meaningful way directly from Javascript. This sounds crazy to me.

xhr.responseBody is accessible from VBScript, so the obvious workaround is to define a method in VBScript in the webpage, and then call that method from Javascript. See jsdap for one example.

 


Yes, the answer I came up with for reading binary data via XHR in IE, is to use VBScript injection. This was distasteful to me at first, but, I look at it as just one more browser dependent bit of code. (The regular XHR and responseText works fine in other browsers; you may have to coerce the mime type with XMLHttpRequest.overrideMimeType(). This isn’t available on IE).

This is how I got a thing that works like responseText in IE, even for binary data. First, inject some VBScript as a one-time thing, like this:

The JS class I’m using that reads binary files exposes a single interesting method, readCharAt(i), which reads the character (a byte, really) at the i’th index. This is how I set it up:

The conversion code was provided by Miskun.

Very fast, works great.


I would suggest two other (fast) options:

  1. First, you can use ADODB.Recordset to convert the byte array into a string. I would guess that this object is more common that ADODB.Stream, which is often disabled for security reasons. This option is VERY fast, less than 30ms for a 500kB file.
  2. Second, if the Recordset component is not accessible, there is a trick to access the byte array data from Javascript. Send your xhr.responseBody to VBScript, pass it through any VBScript string function such as CStr (takes no time), and return it to JS. You will get a weird string with bytes concatenated into 16-bit unicode (in reverse). You can then convert this string quickly into a usable bytestring through a regular expression with dictionary-based replacement. Takes about 1s for 500kB.

For comparison, the byte-by-byte conversion through loops takes several minutes for this same 500kB file, so it’s a no-brainer :) Below the code I have been using, to insert into your header. Then call the function ieGetBytes with your xhr.responseBody.

 

使用if(!+”\v1″ && !”1″[0])来判断浏览器

使用if(!+”\v1″ && !”1″[0])来判断浏览器

其实就是利用各浏览器对转义字符”\v”的理解
在ie浏览器中,”\v”没有转义,得到的结果为”v”
而在其他浏览器中”\v”表示一个垂直制表符(一定程度上相当于空格)
所以ie解析的”\v1″ 为 “v1”
而其他浏览器解析到 “\v1” 为 “1”
在前面加上一个”+”是为了把后面的字符串转变成数字

由于ie认为”\v1″为”v1″,所以前面的加上加号无法转变成数字,为NaN
其他浏览器均能变成 1

再因为js与c语言类似,进行逻辑判断时可使用数字,并且 0 为 false,其他数字则为true
所以 !1 = false ,于是其他浏览器均返回false

js在遇到如下几个值会返回false:undefined、null、NaN,所以ie中 !NaN = true

浅谈document.domain

原文:http://yanni4night.com/2014/04/23/setting-document-domain/

在需要主子域跨域技术的应用场景中,父 frame 和子 frame 设置相同的 document.domain 是一种特别常用的方式,我们可以看见腾讯公司的页面中很多都会有一句:

qq.com 域页面的登录行为很多都是依赖这种方式与iframe结合来实现的。

事实上,W3C 的 DOM 2 HTML标准将 document.domain定义为只读的:

domain of type DOMString, readonly The domain name of the server that served the document, or null if the server cannot be identified by a domain name.

HTML5 草案 中有关于对 document.domain赋值的内容。

在 Webkit 的 Document.idl 源码中对 domain 有这样的定义:

这也说明了 domain 设置为“writable” 仅用于页面脚本:即允许主子域脚本进行通信,但不涉及 localStorageindexedDB 和 XMLHttpRequest 的共享。目前市场上主流浏览器都支持 domain可写,可以满足几乎所有主子域脚本通信需求,但在特殊情况下也有些许不同。

所有浏览器都不支持设置 domain 为当前域子域或不完整的超域,比如当前域为 “abc.google.com” ,那么设置domain 为 “www.abc.google.com” 或”ogle.com” 都是不允许的。现在测试各个浏览器在 host 为以下情形下设置不同domain的反应:

  • 为IP地址
  • 单节域名
  • 多节域名

测试 host 为 “google”、“www.google.com”、“10.11.202.231”。由子域名向父域名测试,因此前面的测试不会对后面的测试造成干扰。

UA/host google www.google.com 10.11.202.231
Firefox(Mac/Windows/Android) s.ff

 

m.ff ip.ff
Safari(iOS/Mac/Windows) s.safari m.safari ip.safari
IE6~7 s.ie67 m.ie67 ip.ie67
Chrome(Mac,Windows)
IE8~10
Opera(presto内核,Mac  / Windows )
s.chrome-ie810-opera m.chrome-ie810-opera ip.chrome-ie810-opera
IE(WP8) 无法打开 m.chrome-ie810-opera ip.chrome-ie810-opera

由上表可得出以下结论:

  • Firefox可以接受带 port 的父域名,但是任意 port 都会被忽略,其它浏览器则会报错;
  • 对于IP地址,IE6、IE7和Safari简单地将其当做为域名;
  • 仅Safari允许将 domain 设置为最后一节域名。Safari 以及 国内几乎所有带 webkit 内核的浏览器 使用了一种相对简单的方式,即在字符串层面上新的domain 是当前 domain 的“父域名”即可,可以从 webkit 中 Document.cpp 文件的源代码中看出:

因此即使是IP地址或是最后一节 domain 也会被允许设置。Internet Explorer 不开源,但可以猜测其对多节域名进行了最后一节域名限制,在 IE8+ 上增加了IP地址限制。Firefox 在3.0版本增加了此限制。对于单节域名如 http://hello/,所有浏览器都一致性地允许设置,当然,这相当于设置 domain 为自身。

Firefox浏览器忽略 port 的行为初衷不得而知,但可以测试该特性是在3.0版本上增加的。

值得一提的是,chromium 项目对 webkit 进行了一些修改,从而带来了一些新的特性,观察 Document.cpp 文件的源代码:

可见除了支持HTML5的 sandbox 之外,还增加了IP地址检测,因此 Chrome 才不会像Safari那样允许IP地址的一段设置为 domain。特别地,Chrome 还进行了顶级域名检测, chromium 项目会生成一个effective_tld_names.gperf 文件,提供了很多域名列表,末尾标记不为0的域名将不能设置为document.domain。比如,一个域名为www.english.uk的页面,在 Chrome 下将不能设置 document.domain为 english.uk,因为 english.uk 被认为是顶级域名从而报错:

SecurityError: Failed to set the ‘domain’ property on ‘Document’: ‘english.uk’ is a top-level domain.

这部分逻辑的一些代码来自 Mozilla ,因此Firefox (3.0+)也具有同样的特性。

截止今天(2014-04-24),这个列表至少包含472个顶级域名,包括孟加拉国、文莱、库克群岛、塞浦路斯、厄立特里亚、埃塞俄比亚、斐济、马尔维纳斯群岛、关岛、以色列、牙买加、肯尼亚、柬埔寨、科威特、缅甸、莫桑比克、尼加拉瓜、尼泊尔、新西兰、巴布亚新几内亚、土耳其、英国、也门、南非、赞比亚、津巴布韦等国家和地区的顶级域名。想必这些国家的网站在设置 document.domain 时会遇到一些困难了:)。

在对IE浏览器进行测试时,也发现了一些奇怪的事情。实验“aa.bb.cc.dd”域名,发现在 IE8+ 下将不能设置document.domain 为“cc.dd”。经过反复测试发现 IE8+在多节域名下允许设置 的双节域名中,两节单词中要至少有一个大于2个字母,换言之,下列域名都是不允许的:

  • sa.cn
  • o.jp
  • x.m

但下列是允许的:

  • sax.cn
  • o.com
  • xxx.k

暂不知微软用意为何,但可以联想到,新浪微博的短域名 t.cn在有下一级域名的情形下,将不能设置document.domain为 t.cn

即便拥有上面的诸多问题,不过都属于特例,除了 IE8+ 的短域名问题,其它基本都不会在日常的开发中遇到。

参考
  1. http://javascript.info/tutorial/same-origin-security-policy
  2. http://msdn.microsoft.com/en-us/library/ie/ms533740(v=vs.85).aspx
  3. https://developer.mozilla.org/en-US/docs/Web/API/document.domain

IE6,7通过opener hack方式实现完美跨域

转自 http://www.cnblogs.com/xueduanyang/archive/2011/08/23/2150090.html

之前在项目的时候,有需要跨域请求和处理一些大数据量得数据,对于服务端提交的数据非常的之大,get的URL长度限制满足不了需求,又由于跨域的影响,一直很头痛数据传输的问题。于是乎,上网搜了搜一些跨域的解决方案,无非了iframe嵌iframe,通过window.name或者hash,做跳板,都受到url长度的限制,不是很理想。我们都知道在HTML5中,提供了一种postMessage的消息机制,可以在不同域的页面上,互相通过window.postMessage(datastring,’limitDomain’)的方式传递消息。在需要触发的页面注册onMessage事件,event的data属性就是传递datastring文本。再配合老道的JSON.parse就可以完美的传递json格式的对象了。可惜的是目前PostMessage只在IE8,FF和Chrome现版本提供了实现。对于老版本的IE6,7没有提供实现。

于是在google搜索的时候,无意中发现某高人的Blog提供了一种称之为IE6,7 opener hack的方式实现跨域,据说是google的工程师率先发现的这个bug,fackbook的登陆页面就是利用了这个bug实现了postMessage的跨域。

可惜,google了半天,详细资料基本找不到,也没有找到一个具体的例子,于是自己捣鼓了一下,写了个例子,放上来。

下面我们来看下,如何利用这个bug的例子

hosts配置

127.0.0.1 www.a.com
127.0.0.1 www.b.com

test.htm

 

test1.htm

 

执行http://www.a.com/test.htm就可以看到结果

我们可以看到,在IE6,7下,只要重置了window对象的opener为一个{}对象,在父页面设置了iframe的window.opener为一个{}之后,在iframe里面就可以通过opener调用parent的方法,在iframe重置parent.opener为一个{}对象之后,在parent就可以调用iframe的方法。

*还有一种说法是可以设置opener为function(){},通过new opener()来调用

总结,通过IE6,7的hack,我们可以比较完美的实现postMessage在各大主流浏览器的兼容,以后跨域又多了一项利器。不过比较遗憾的事,重置opener之后,对于window.open打开的窗口,就不能很好的操作了,在IE6,7下。