加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 创业 > C语言 > 正文

JS概念:前端跨域

发布时间:2020-12-15 00:27:51 所属栏目:C语言 来源:网络整理
导读:总结 document.domain:基础域名相同前提下,更改document.domain可使iframe内容可操作 window.name:先访问跨域页面获取数据window.name,再将src设置回来,window.name不变,实现跨域。 ps:这里额外补充一下,能懂就懂,不懂也没事。 有的人叫根域名,如

总结

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.comcdf.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代码如下:

利用 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 的对比

  1. CORS 除了 GET 方法外,也支持其它的 HTTP 请求方法如 POST、 PUT 等。
  2. CORS 可以使用 XmlHttpRequest 进行传输,所以它的错误处理方式比 JSONP 好。
  3. JSONP 可以在不支持 CORS 的老旧浏览器上运作。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读