百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 文章教程 > 正文

常见跨域解决方案(一)

yund56 2025-03-30 18:39 17 浏览

什么是跨域

跨域是指一个域下的文档或脚本试图去请求另一个域下的资源,这里跨域是广义的。

广义的跨域:

1)资源跳转:A链接、重定向、表单提交

2)资源嵌入:、<script>、、等dom标签,还有样式中background:url()、@font-face()等文件外链

3)脚本请求:js发起的ajax请求、dom和js对象的跨域操作等

我们通常所说的跨域是狭义的,是由浏览器同源策略限制的一类请求场景。

什么是同源策略

同源策略/SOP(Same origin policy)是一种约定,由Netscape公司1995年引入浏览器,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,浏览器很容易受到XSS、CSRF等攻击。所谓同源是指"协议+域名+端口"三者相同,即便两个不同的域名指向同一个ip地址,也非同源。

同源策略限制以下几种行为:

1)Cookie、LocalStorage 和 IndexDB 无法读取

2)DOM 和 Js对象无法获得

3)AJAX 请求不能发送

常见跨域场景

常见跨域场景

特别注意两点:

1)如果是协议和端口造成的跨域问题“前台”是无能为力的,

2)在跨域问题上,域仅仅是通过“URL的首部”来识别而不会去尝试判断相同的ip地址对应着两个域或两个域是否在同一个ip上。“URL的首部”指 协议+域名+端口。

解决跨域的几种方法

1、通过jsonp跨域

2、iframe跨域

1)document.domain + iframe 跨域

2)location.hash + iframe 跨域

3)window.name + iframe 跨域

3、postMessage跨域

4、跨域资源共享(CORS)

5、nginx代理跨域

6、nodejs中间件代理跨域

7、WebSocket协议跨域

一、通过jsonp跨域

通常为了减轻web服务器的负载,我们把js、css,img等静态资源分离到另一台独立域名的服务器上,在html页面中再通过相应的标签从不同域名下加载静态资源,而被浏览器允许,基于此原理,我们可以通过动态创建script,再请求一个带参网址实现跨域通信。

JSONP包含两部分:回调函数和数据。回调函数:当响应到来时要放在当前页面被调用的函数。数据:传入回调函数中的json数据,也就是回调函数的参数。

1、原生实现

<script>
    var script = document.createElement('script');
    script.type = 'text/javascript';

    // 传参一个回调函数名给后端,方便后端返回时执行这个在前端定义的回调函数
    script.src = 'http://www.tunan666.com:8080/login?user=admin&callback=handleCallback';
    document.head.appendChild(script);

    // 回调执行函数
    function handleCallback(res) {
        alert(JSON.stringify(res));
    }
 </script>

服务端返回如下(返回时即执行全局函数):

handleCallback({"status": true, "user": "admin"})

2、jquery ajax

$.ajax({
    url: 'http://www.tunan666.com:8080/login',
    type: 'get',
    dataType: 'jsonp',  // 请求方式为jsonp
    jsonpCallback: "handleCallback",    // 自定义回调函数名
    data: {}
});

3、vue.js

this.$http.jsonp('http://www.tunan666.com:8080/login', {
    params: {},
    jsonp: 'handleCallback'
}).then((res) => {
    console.log(res); 
})

4、后端node.js

var querystring = require('querystring');
var http = require('http');
var server = http.createServer();

server.on('request', function(req, res) {
    var params = qs.parse(req.url.split('?')[1]);
    var fn = params.callback;

    // jsonp返回设置
    res.writeHead(200, { 'Content-Type': 'text/javascript' });
    res.write(fn + '(' + JSON.stringify(params) + ')');

    res.end();
});

server.listen('8080');
console.log('Server is running at port 8080...');

jsonp虽然很简单,但是有如下缺点:

1)安全问题:请求代码中可能存在安全隐患

2)要确定jsonp请求是否失败并不容易

3)只能实现get一种请求

二、iframe跨域

1、document.domain + iframe 跨域

此方案仅限主域相同,子域不同的跨域应用场景。

实现原理:两个页面都通过js强制设置document.domain为基础主域,就实现了同域。

1)父窗口:(
http://www.tunan666.com/a.html)


<script>
    document.domain = 'tunan666.com';
    var user = 'admin';
</script>

2)子窗口:(
http://child.tunan666.com/b.html)

<script>
    document.domain = 'tunan666.com';
    // 获取父窗口中变量
    alert('get js data from parent ---> ' + window.parent.user);
</script>

2、location.hash + iframe 跨域

实现原理:a与b跨域相互通信,通过中间页c来实现。三个页面,不同域之间利用iframe的location.hash传值,相同域之间直接js访问来通信。

具体实现:A域:a.html -> B域:b.html -> A域:c.html,a与b不同域只能通过hash值单向通信,b与c也不同域也只能单向通信,但c与a同域,所以c可通过parent.parent访问a页面所有对象。

1)a.html:(http://www.tunan666.com/a.html)


<script>
    var iframe = document.getElementById('iframe');

    // 向b.html传hash值
    setTimeout(function() {
        iframe.src = iframe.src + '#user=admin';
    }, 1000);
    
    // 开放给同域c.html的回调方法
    function onCallback(res) {
        alert('data from c.html ---> ' + res);
    }
</script>

2)b.html:(http://www.tn666.com/b.html)


<script>
    var iframe = document.getElementById('iframe');

    // 监听a.html传来的hash值,再传给c.html
    window.onhashchange = function () {
        iframe.src = iframe.src + location.hash;
    };
</script>

3)c.html:(http://www.tunan666.com/c.html)

<script>
    // 监听b.html传来的hash值
    window.onhashchange = function () {
        // 再通过操作同域a.html的js回调,将结果传回
        window.parent.parent.onCallback('hello: ' + location.hash.replace('#user=', ''));
    };
</script>

3、window.name + iframe 跨域

window.name属性的独特之处:name值在不同的页面(甚至不同域名)加载后依旧存在,并且可以支持非常长的 name 值(2MB)。

通过iframe的src属性由外域转向本地域,跨域数据即由iframe的window.name从外域传递到本地域。这个就巧妙地绕过了浏览器的跨域访问限制,但同时它又是安全操作。

1)a.html:(http://www.tunan666.com/a.html)

var proxy = function(url, callback) {
    var state = 0;
    var iframe = document.createElement('iframe');

    // 加载跨域页面
    iframe.src = url;

    // onload事件会触发2次,第1次加载跨域页,并留存数据于window.name
    iframe.onload = function() {
        if (state === 1) {
            // 第2次onload(同域proxy页)成功后,读取同域window.name中数据
            callback(iframe.contentWindow.name);
            destoryFrame();


        } else if (state === 0) {
            // 第1次onload(跨域页)成功后,切换到同域代理页面
            iframe.contentWindow.location = 'http://www.tunan666.com/proxy.html';
            state = 1;
        }
    };

    document.body.appendChild(iframe);

    // 获取数据以后销毁这个iframe,释放内存;这也保证了安全(不被其他域frame js访问)
    function destoryFrame() {
        iframe.contentWindow.document.write('');
        iframe.contentWindow.close();
        document.body.removeChild(iframe);
    }
};

// 请求跨域b页面数据
proxy('http://www.tn666.com/b.html', function(data){
    alert(data);
});

2)proxy.html:(http://www.tunan666.com/proxy….

中间代理页,与a.html同域,内容为空即可。

3)b.html:(http://www.tn666.com/b.html)

<script>
    window.name = 'This is tn666 data!';
</script>

三、postMessage跨域

postMessage是HTML5 XMLHttpRequest Level 2中的API,且是为数不多可以跨域操作的window属性之一,它可用于解决以下方面的问题:

1)页面和其打开的新窗口的数据传递

2)多窗口之间消息传递

3)页面与嵌套的iframe消息传递

4)上面三个场景的跨域数据传递

用法:postMessage(data,origin)方法接受两个参数

data:html5规范支持任意基本类型或可复制的对象,但部分浏览器只支持字符串,所以传参时最好用JSON.stringify()序列化。

origin:协议+主机+端口号,也可以设置为"*",表示可以传递给任意窗口,如果要指定和当前窗口同源的话设置为"/"。

1、a.html:(
http://www.tunan666.com/a.html)


<script>       
    var iframe = document.getElementById('iframe');
    iframe.onload = function() {
        var data = {
            name: 'aym'
        };
        // 向tn666传送跨域数据
        iframe.contentWindow.postMessage(JSON.stringify(data), 'http://www.tn666.com');
    };

    // 接受tn666返回数据
    window.addEventListener('message', function(e) {
        alert('data from tn666 ---> ' + e.data);
    }, false);
</script>

2、b.html:(
http://www.tn666.com/b.html)

<script>
    // 接收tunan666的数据
    window.addEventListener('message', function(e) {
        alert('data from tunan666 ---> ' + e.data);

        var data = JSON.parse(e.data);
        if (data) {
            data.number = 16;

            // 处理后再发回tunan666
            window.parent.postMessage(JSON.stringify(data), 'http://www.tunan666.com');
        }
    }, false);
</script>


下一篇文章介绍剩下的几种方法:

4、跨域资源共享(CORS)

5、nginx代理跨域

6、nodejs中间件代理跨域

7、WebSocket协议跨域


敬请期待~

相关推荐

SM小分队Girls on Top,女神战队少了f(x)?

这次由SM娱乐公司在冬季即将开演的smtown里,将公司的所有女团成员集结成了一个小分队project。第一位这是全面ACE的大姐成员权宝儿(BoA),出道二十年,在日本单人销量过千万,韩国国内200...

韩国女团 aespa 首场 VR 演唱会或暗示 Quest 3 将于 10 月推出

AmazeVR宣布将在十月份举办一场现场VR音乐会,观众将佩戴MetaQuest3进行体验。韩国女团aespa于2020年11月出道,此后在日本推出了三张金唱片,在韩国推出了...

韩网热议!女团aespa成员Giselle在长腿爱豆中真的是legend

身高163的Giselle,长腿傲人,身材比例绝了...

假唱而被骂爆的女团:IVE、NewJeans、aespa上榜

在韩国,其实K-pop偶像并不被认为是真正的歌手,因为偶像们必须兼备舞蹈能力、也经常透过对嘴来完成舞台。由于科技的日渐发达,也有许多网友会利用消音软体来验证K-pop偶像到底有没有开麦唱歌,导致假唱这...

新女团Aespa登时尚大片 四个少女四种style

来源:环球网

韩国女团aespa新歌MV曝光 画面梦幻造型超美

12月20日,韩国女团aespa翻唱曲《DreamsComeTrue》MV公开,视频中,她们的造型超美!WINTER背后长出一双梦幻般的翅膀。柳智敏笑容甜美。宁艺卓皮肤白皙。GISELLE五官精致...

女网友向拳头维权,自称是萨勒芬妮的原型?某韩国女团抄袭KDA

女英雄萨勒芬妮(Seraphine)是拳头在2020年推出的第五位新英雄,在还没有正式上线时就备受lsp玩家的关注,因为她实在是太可爱了。和其他新英雄不同的是,萨勒芬妮在没上线时就被拳头当成虚拟偶像来...

人气TOP女团是?INS粉丝数见分晓;TWICE成员为何在演唱会落泪?

现在的人气TOP女团是?INS粉丝数见分晓!现在爱豆和粉丝之间的交流方法变得多种多样,但是Instagram依然是主要的交流手段。很多粉丝根据粉丝数评价偶像的人气,拥有数百、数千万粉丝的组合作为全球偶...

韩国女团MVaespa Drama MV_韩国女团穿超短裙子跳舞

WelcometoDrama.Pleasefollow4ruleswhilewatchingtheDrama.·1)Lookbackimmediatelywhenyoufe...

aespa师妹团今年将出道! SM职员亲口曝「新女团风格、人数」

记者刘宛欣/综合报导南韩造星工厂SM娱乐曾打造出东方神起、SUPERJUNIOR、少女时代、SHINee、EXO等传奇团体,近年推出的aespa、RIIZE更是双双成为新生代一线团体,深受大众与粉丝...

南韩最活跃的女团aespa,新专辑《Girls》即将发布,盘点昔日经典

女团aespa歌曲盘点,新专辑《Girls》即将发布,期待大火。明天也就是2022年的7月8号,aespa新专辑《Girls》即将发行。这是继首张专辑《Savage》之后,时隔19个月的第二张专辑,这...

章泽天女团aespa出席戛纳晚宴 宋康昊携新片亮相

搜狐娱乐讯(山今/文玄反影/图科明/视频)法国时间5月23日晚,女团aespa、宋康昊、章泽天等明星亮相戛纳晚宴。章泽天身姿优越。章泽天肩颈线优越。章泽天双臂纤细。章泽天仪态端正。女团aespa亮...

Aespa舞台暴露身高比例,宁艺卓脸大,柳智敏有“TOP”相

作为SM公司最新女团aespa,初舞台《BlackMamba》公开,在初舞台里,看得出来SM公司是下了大功夫的,虽然之前SM公司新出的女团都有很长的先导片,但是aespa显然是有“特殊待遇”。运用了...

AESPA女团成员柳智敏karina大美女

真队内速度最快最火达成队内首个且唯一两百万点赞五代男女团中输断层第一(图转自微博)...

对来学校演出的女团成员语言性骚扰?韩国这所男高的学生恶心透了

哕了……本月4日,景福男子高中相关人士称已经找到了在SNS中上传对aespa成员进行性骚扰文章的学生,并开始着手调查。2日,SM娱乐创始人李秀满的母校——景福高中迎来了建校101周年庆典活动。当天,S...