总结
document.domain:基础域名相同前提下,更改document.domain可使iframe内容可操作
window.name:先访问跨域页面获取数据window.name,再将src设置回来,window.name不变,实现跨域。
ps:这里额外补充一下,能懂就懂,不懂也没事。
有的人叫根域名,如:sojson.com、baidu.com、sina.com、sina.com.cn、sina.cn.net 等等。
是指增加了一级,包括www。如:www.sojson.com、icp.sojson.com、zhidao.baidu.com、www.baidu.com 等等。有人把www.sojson.com叫一级域名这是错误的。
三级、四级一直下去,照理推下去就明白了,腾讯和新浪很多这样的域名,甚至有5-6级的。都是用qq.com。这里想说一个什么事情呢,就是上面讲解的说要一级域名一致,其实严格来说是父域名一致。
举个栗子:
abc.www.baidu.com 和 cdf.www.baidu.com 他们就都可以document.domain 指定到 www.baidu.com 即可。
跨域问题产生的场景
当要在在页面中使用js获取其他网站的数据时,就会产生跨域问题,比如在网站中使用ajax请求其他网站的天气、快递或者其他数据接口时以及hybrid app中请求数据,浏览器就会提示以下错误。这种场景下就要解决js的跨域问题。
XMLHttpRequest cannot load http://你请求的域名. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://当前页的域名' is therefore not allowed access.
只要 协议 、 域名 、 端口 有任何一个 不同,都被当作是 不同 的域。
跨域信息传输到底在哪里被阻止?
如果让 服务器3000 上的页面向 服务器 3001 发起请求会怎样呢?
将请求页面中的 ajax 请求路径改为:
$.ajax({
...
url: 'http://localhost:3001/ajax/deal',...
});
服务器3001 对应的处理函数与 服务器3000 类似:
app.post('/ajax/deal',function(req,res) {
console.log("server accept: ",req.body.name,req.body.id)
var data = {
name: req.body.name + ' - server 3001 process',id: req.body.id + ' - server 3001 process'
}
res.send(data)
res.end()
})
结果如下: 3000_to_3001_error 结果证明了我们上面所说的端口号不同,发生了跨域请求的调用。
需要注意的是,服务器 3001 控制台有输出:
server accept: chiaki 3001
这说明跨域请求并非是浏览器限制了发起跨站请求,而是请求可以正常发起,到达服务器端,但是服务器返回的结果会被浏览器拦截。
图片可以从任何URL中加载,所以将img的src设置成其他域的URL,即可以实现简单的跨域,可以使用onload和onerror事件来确定是否接受到了响应。 var img=new Image(); img.src=''; img.onerror=function(){ alert('error'); } img.onload=function(){ alert('success'); } 这里新建了一个img对象,给出的url是博客地址,这里是个error事件,所以弹出error;如果将URL改为一张图片,就会弹出onload加载信息success,从而实现了简单的跨域。 使用图片ping跨域只能发送get请求,并且不能访问响应的文本,只能监听是否响应而已 ,可以用来追踪广告点击。
基本上,它就像是跨域的AJAX,但不是浏览器跟服务器之间交互,而是在两个客户端之间通信。
A(B) B(C) C可更改A的hash 现阶段index.html中可以更改引入的iframe的src的hash。header.html中通过定时器判断hash值的变化,做出相应的操作。但是在header.html不可以直接操作index.html的hash。如果直接用parent.locatin.hash = name;会出现 222221113324禁止跨域操作
此时需要引入一个代理文件(crossdomain.html),此文件与index.html同域,因此,index.html可以和crossdomian.html相互通信。通过在header.html中改变crossdomain.html的hash,在crossdomain.html中监听 hash的变化,在通过parent.parent.location.hash改变index.html的hash值。
location.hash + iframe跨域的优点:
1.可以解决域名完全不同的跨域 2.可以实现双向通讯
location.hash + iframe跨域的缺点:
location.hash会直接暴露在URL里 ,并且在一些浏览器里会产生历史记录,数据安全性不高也影响用户体验。另外由于URL大小的限制,支持传递的数据量 也不大。
我们也可以给document.domain(老东西了)属性赋值,不过是有限制的,你只能赋成当前的域名或者基础域名。 意味着document.domain只能实现子域间跨域
比如在:aaa.com的一个网页(a.html)里面 利用iframe引入了一个bbb.com里的一个网页(b.html)。
这时在a.html里面可以看到b.html里的内容,但是却不能利用javascript来操作它。因为这两个页面属于不同的域,在操作之前,js会检测两个页面的域是否相等,如果相等,就允许其操作,如果不相等,就会拒绝操作。
这里不可能把a.html与b.html利用JS改成同一个域的。因为它们的基础域名不相等。(强制用JS将它们改成相等的域的话会报跟上面一样的"参数无效错误。") 所以如果在a.html里引入aaa.com里的另一个网页,是不会有这个问题的,因为域相等。
有另一种情况,两个子域名:
aaa.xxx.com
bbb.xxx.com
aaa里的一个网页(a.html)引入了bbb 里的一个网页(b.html), 这时a.html里同样是不能操作b.html里面的内容的。
因为document.domain不一样,一个是aaa.xxx.com,另一个是bbb.xxx.com。
这时我们就可以通过Javascript,将两个页面的domain改成一样的,
需要在a.html里与b.html里都加入:
复制代码 代码如下:
document.domain = "xxx.com";
这样这两个页面就可以互相操作了。也就是实现了同一基础域名之间的"跨域" 。
什么是基础域名?
比如:
javascript:alert(document.domain = "52php.cn"); //52php.cn
javascript:alert(document.domain = "www.52php.cn"); //www.52php.cn
上面的赋值都是成功的,因为www.52php.cn是当前的域名,而52php.cn是基础域名。
但是下面的赋值就会出来"参数无效"的错误:
javascript:alert(document.domain = "cctv.net"); //参数无效
javascript:alert(document.domain = "www.52php.cn"); //参数无效
因为cctv.net与www.52php.cn不是当前的域名也不是当前域名的基础域名,所以会有错误出现。 这是为了防止有人恶意修改document.domain来实现跨域偷取数据。
利用iframe的window.name可共享 通信(老东西了)
有三个页面:
a.com/app.html:应用页面。
a.com/proxy.html:代理文件,一般是一个没有任何内容的html文件,需要和应用页面在同一域下。(换回来才能访问window.name,window.name不会被覆盖)
b.com/data.html:应用页面需要获取数据的页面,可称为数据页面。
在应用页面(a.com/app.html)中创建一个iframe,把其src指向数据页面(b.com/data.html)。 数据页面会把数据附加到这个iframe的window.name上,data.html代码如下:
在应用页面(a.com/app.html)中监听iframe的onload事件,在此事件中设置这个iframe的src指向本地域的代理文件(代理文件和应用页面在同一域下,所以可以相互通信)。
iframe.src = 'http://b.com/data.html';
if (iframe.attachEvent) {
iframe.attachEvent('onload',loadfn);
} else {
iframe.onload = loadfn;
}
获取数据以后销毁这个iframe,释放内存;这也保证了安全(不被其他域frame js访问)。
利用 JSONP 实现跨域调用
什么是JSONP
JSONP 是 JSON 的一种使用模式,可以解决主流浏览器的跨域数据访问问题。其原理是根据 XmlHttpRequest 对象受到同源策略的影响,而
这样从服务器返回的代码就可以直接在这个 script 标签中运行了。
JSONP 总结
至此,我们了解了 JSONP 的原理以及实现方式,它帮我们实现前端跨域请求,但是在实践的过程中,我们还是可以发现它的不足:
数据格式:只能使用 GET 方法发起请求,这是由于 script 标签自身的限制决定的。
信息反馈:不能很好的发现错误,并进行处理。与 Ajax 对比,由于不是通过 XmlHttpRequest 进行传输,所以不能注册 success、 error 等事件监听函数。
使用 CORS 实现跨域调用
什么是 CORS?
Cross-Origin Resource Sharing(CORS)跨域资源共享是一份浏览器技术的规范,提供了 Web 服务从不同域传来沙盒脚本的方法,以避开浏览器的同源策略,是 JSONP 模式的现代版。与 JSONP 不同,CORS 除了 GET 要求方法以外也支持其他的 HTTP 要求。用 CORS 可以让网页设计师用一般的 XMLHttpRequest,这种方式的错误处理比 JSONP 要来的好。另一方面,JSONP 可以在不支持 CORS 的老旧浏览器上运作。现代的浏览器都支持 CORS。
假设本域是my.com,外域是sina.com,只要响应头Access-Control-Allow-Origin为,或者是*,本次请求就可以成功。
CORS 的实现
服务器 3001上对应的处理函数:
app.post('/cors',res) {
res.header("Access-Control-Allow-Origin","*");
res.header("Access-Control-Allow-Headers","X-Requested-With");
res.header("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");
res.header("X-Powered-By",' 3.2.1')
res.header("Content-Type","application/json;charset=utf-8");
var data = {
name: req.body.name + ' - server 3001 cors process',id: req.body.id + ' - server 3001 cors process'
}
console.log(data)
res.send(data)
res.end()
})
CORS 与 JSONP 的对比
- CORS 除了 GET 方法外,也支持其它的 HTTP 请求方法如 POST、 PUT 等。
- CORS 可以使用 XmlHttpRequest 进行传输,所以它的错误处理方式比 JSONP 好。
- JSONP 可以在不支持 CORS 的老旧浏览器上运作。
(编辑:李大同)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|