Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >优秀博客文章 | javascript跨域方法总结

优秀博客文章 | javascript跨域方法总结

作者头像
用户1467662
发布于 2019-04-19 08:24:40
发布于 2019-04-19 08:24:40
61400
代码可运行
举报
文章被收录于专栏:农夫安全农夫安全
运行总次数:0
代码可运行

跨域方法总结

最近面试问的挺多的一个问题,就是JavaScript的跨域问题。在这里,对跨域的一些方法做个总结。由于浏览器的同源策略,不同域名、不同端口、不同协议都会构成跨域;但在实际的业务中,很多场景需要进行跨域传递信息,这样就催生出多种跨域方法。

0x01 具备src的标签

原理:所有具有src属性的HTML标签都是可以跨域的

在浏览器中,<script><img><iframe><link>这几个标签是可以加载跨域(非同源)的资源的,并且加载的方式其实相当于一次普通的GET请求,唯一不同的是,为了安全起见,浏览器不允许这种方式下对加载到的资源的读写操作,而只能使用标签本身应当具备的能力(比如脚本执行、样式应用等等)。

0x02 JSONP跨域

原理:<script>是可以跨域的,而且在跨域脚本中以直接回调当前脚本的函数

script标签是可以加载异域的JavaScript并执行的,通过预先设定好的callback函数来实现和母页面的交互。它有一个大名,叫做JSONP跨域,JSONP是JSON with Padding的略称。它是一个非官方的协议,明明是加载script,为啥和JSON扯上关系呢?原来就是这个callback函数,对它的使用有一个典型的方式,就是通过JSON来传参,即将JSON数据填充进回调函数,这就是JSONP的JSON+Padding的含义。JSONP只支持GET请求。

前端代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<script type="text/javascript">
    function dosomething(jsondata){
//处理获得的json数据
    }
</script>
<script src="http://haorooms.com/data.php?callback=dosomething"></script>

后端代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<?php
$callback = $_GET['callback'];//得到回调函数名
$data = array('a','b','c');//要返回的数据
echo $callback.'('.json_encode($data).')';//输出
?>

0x03 跨域资源共享(CORS)

原理:服务器设置Access-Control-Allow-Origin HTTP响应头之后,浏览器将会允许跨域请求

CORS是HTML5标准提出的跨域资源共享(Cross Origin Resource Share),支持GET、POST等所有HTTP请求。CORS需要服务器端设置Access-Control-Allow-Origin头,否则浏览器会因为安全策略拦截返回的信息。

配置文件:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Access-Control-Allow-Origin: *              # 允许所有域名访问,或者
Access-Control-Allow-Origin: http://a.com   # 只允许所有域名访问

CORS又分为简单跨域和非简单跨域请求,有关CORS的详细介绍请看阮一峰的跨域资源共享CORS详解,里面讲解的非常详细。

0x04 document.domain

原理:相同主域名不同子域名下的页面,可以设置document.domain让它们同域

我们只需要在跨域的两个页面中设置document.domain就可以了。修改document.domain的方法只适用于不同子域的框架间的交互,要载入iframe页面。

例如:

1. 在页面

http://a.example.com/a.html

设置document.domain

代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<iframe id = "iframe" src="http://b.example.com/b.html" onload = "test()"></iframe>
<script type="text/javascript">
    document.domain = 'example.com';//设置成主域
    function test(){
        alert(document.getElementById('iframe').contentWindow);//contentWindow 可取得子窗口的 window 对象
    }
</script>

2. 在页面

http:// b.example.com/b.html

中设置document.domain

代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<script type="text/javascript">
    document.domain = 'example.com';//在iframe载入这个页面也设置document.domain,使之与主页面的document.domain相同
</script>

0x05 window.name

原理:window对象有个name属性,该属性有个特征:即在一个窗口(window)的生命周期内,窗口载入的所有的页面都是共享一个window.name的,每个页面对window.name都有读写的权限,window.name是持久存在一个窗口载入过的所有页面中的。

这里有三个页面:

sever.com/a.html 数据存放页面

agent.com/b.html 数据获取页面

agent.com/c.html 空页面,做代理使用

a.html中,设定window.name作为需要传递的值

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<script>
    window.name = 'I was there!';
    alert(window.name);
</script>

b.html中,当iframe加载后将iframe的src指向同域的c.html,这样就可以利用iframe.contentWindow.name获取要传递的值了

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<body>
  <script type="text/javascript">
  iframe = document.createElement('iframe');
  iframe.style.display = 'none';
  var state = 0;
  iframe.onload = function() {
    if(state === 1) {
      var data = JSON.parse(iframe.contentWindow.name);
      alert(data);
      iframe.contentWindow.document.write('');
      iframe.contentWindow.close();
      document.body.removeChild(iframe);
    } else if(state === 0) {
      state = 1;
      iframe.contentWindow.location = 'http://agent.com/c.html';
    }
  };
  iframe.src = 'http://sever.com/a.html';
  document.body.appendChild(iframe);
  </script>
</body>

成功获取跨域数据,效果如下:

0x06 window.postMesage

原理: HTML5新增的postMessage方法,通过postMessage来传递信息,对方可以通过监听message事件来监听信息。可跨主域名及双向跨域。

这里有两个页面:

  1. agent.com/index.html
  2. server.com/remote.html

本地代码index.html

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<body>
    <iframe id="proxy" src="http://server.com/remote.html" onload = "postMsg()" style="display: none" ></iframe>  
    <script type="text/javascript">  
        var obj = {  
            msg: 'hello world'  
        }  
        function postMsg (){  
            var iframe = document.getElementById('proxy');  
            var win = iframe.contentWindow;  
            win.postMessage(obj,'http://server.com');  
        }  
    </script>  
</body>

postMessage的使用方法:

otherWindow.postMessage(message, targetOrigin);

  • otherWindow: 指目标窗口,也就是给哪个window发消息,是 window.frames 属性的成员或者由 window.open 方法创建的窗口
  • message: 是要发送的消息,类型为 String、Object (IE8、9 不支持)
  • targetOrigin: 是限定消息接收范围,不限制请使用 ‘*’

server.com上remote.html,监听message事件,并检查来源是否是要通信的域。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<head>
    <title></title>
    <script type="text/javascript">
        window.onmessage = function(e){
            if(e.origin !== 'http://localhost:8088') return;
            alert(e.data.msg+" from "+e.origin);
        }
    </script>
</head>

成功获取到跨域数据:

0x07 location.hash

原理:

  • 这个办法比较绕,但是可以解决完全跨域情况下的脚步置换问题。原理是利用location.hash来进行传值。www.a.com下的a.html想和www.b.com下的b.html通信(在a.html中动态创建一个b.html的iframe来发送请求)
  • 但是由于“同源策略”的限制他们无法进行交流(b.html无法返回数据),于是就找个中间人:www.a.com下的c.html(注意是www.a.com下的)。
  • b.html将数据传给c.html(b.html中创建c.html的iframe),由于c.html和a.html同源,于是可通过c.html将返回的数据传回给a.html,从而达到跨域的效果。

a.html代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<script>
function startRequest(){  
    var ifr = document.createElement('iframe');  
    ifr.style.display = 'none';  
    ifr.src = 'http://www.b.com/b.html#sayHi'; //传递的location.hash 
    document.body.appendChild(ifr);  
}  
function checkHash() {  
    try {  
        var data = location.hash ? location.hash.substring(1) : '';  
        if (console.log) {  
            console.log('Now the data is '+data);  
        }  
    } catch(e) {};  
}  
setInterval(checkHash, 2000); 
window.onload = startRequest;
</script>

b.html代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<script>
function checkHash(){
  var data = '';
//模拟一个简单的参数处理操作
  switch(location.hash){
    case '#sayHello': data = 'HelloWorld';break;
    case '#sayHi': data = 'HiWorld';break;
    default: break;
  }
  data && callBack('#'+data);
}
function callBack(hash){
// ie、chrome的安全机制无法修改parent.location.hash,所以要利用一个中间的www.a.com域下的代理iframe
  var proxy = document.createElement('iframe');
  proxy.style.display = 'none';
  proxy.src = 'http://localhost:8088/proxy.html'+hash;  // 注意该文件在"www.a.com"域下
  document.body.appendChild(proxy);
}
window.onload = checkHash;
</script>

由于两个页面不在同一个域下,IE、Chrome不允许修改parent.location.hash的值,所以要借助于a.com域名下的一个代理iframe,这里有一个a.com下的代理文件c.html。Firefox可以修改。 c.html代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<script>parent.parent.location.hash = self.location.hash.substring(1);  </script>

直接访问a.html,a.html向b.html发送的消息为”sayHi”;b.html通过消息判断返回了”HiWorld”,并通过c.html改变了location.hash的值

0x08 flash URLLoader

flash有自己的一套安全策略,服务器可以通过crossdomain.xml文件来声明能被哪些域的SWF文件访问,SWF也可以通过API来确定自身能被哪些域的SWF加载。当跨域访问资源时,例如从域baidu.com请求域google.com上的数据,我们可以借助flash来发送HTTP请求。首先,修改域google.com上的crossdomain.xml(一般存放在根目录,如果没有需要手动创建) ,把baidu.com加入到白名单。其次,通过Flash URLLoader发送HTTP请求,最后,通过Flash API把响应结果传递给JavaScript。Flash URLLoader是一种很普遍的跨域解决方案,不过需要支持iOS的话,这个方案就不可行了。

THE END

总的来说,常见的跨域方法如上述。在不同的业务场景下,各有适合的跨域方式。跨域解决了一些资源共享、信息交互的难题,但是有的跨域方式可能会带来安全问题,如jsonp可导致水坑攻击,<img>等标签会被用来进行xss或csrf攻击。所以,在应用跨域的场景,需要格外注意安全问题。

本文转自http://wps2015.org,由农夫安全负责排版发布。我们尊重每一位原创作者,文章内容仅用于技术分享,如有侵权可联系编辑删除。

我们不生产安全,我们只是安全的搬运工 --farmsec

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2018-10-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 网络安全社区悦信安 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
10 种CORS跨域解决方案
这是一个老生常谈的话题,以前我觉得这种基础文章没有什么好写的,最近为了线上问题深入了解底层,确实有点东西,下面汇总成10种方案。
sunsky
2022/09/09
7.6K0
10 种CORS跨域解决方案
九种实用的前端跨域处理方案(转载非原创)
转载来源:https://www.cnblogs.com/ypSharing/p/corsHanlder.html
xlj
2021/09/20
1.6K0
Javascript跨域
如果协议,端口(如果指定了一个)和主机对于两个页面是相同的,则两个页面具有相同的源。
菜的黑人牙膏
2019/01/21
1.1K0
web跨域解决方案
阅读目录 什么是跨域 常用的几种跨域处理方法: 跨域的原理解析及实现方法 总结 摘要:跨域问题,无论是面试还是平时的工作中,都会遇到,本文总结处理跨域问题的几种方法以及其原理,也让自己搞懂这方面的知识,走起。 什么是跨域     在JavaScript中,有一个很重要的安全性限制,被称为“Same-Origin Policy”(同源策略)。这一策略对于JavaScript代码能够访问的页面内容做了很重要的限制,即JavaScript只能访问与包含它的文档在同一域下的内容。   JavaScript这个安全策
hbbliyong
2018/03/06
2.9K0
web跨域解决方案
跨域请求方案 终极版
现在是资源共享的时代,同样也是知识分享的时代,如果你觉得本文能学到知识,请把知识与别人分享。
互扯程序
2018/07/30
3.9K0
Web前端学习笔记之前端跨域知识总结
相信每一个前端er对于跨域这两个字都不会陌生,在实际项目中应用也是比较多的。但跨域方法的多种多样实在让人目不暇接。老规矩,碰到这种情况,就只能自己总结一篇博客,作为记录。
Jetpropelledsnake21
2018/08/10
1.2K0
JSONP && CORS
  前天面试被问到了跨域的问题,自我感觉回答的并不理想,下面我就分享一下整理后的总结分享给大家
超然
2018/08/03
1.4K0
JSONP && CORS
你真的了解跨域吗
相信每个前端对于跨域这两个字都不会陌生,在实际项目中应用也很多,但跨域方法的多种多样让人目不暇接,前段时间公司同事出现了跨域问题,又一时找不到问题所在,所以在此总结下跨域知识,一篇由浅入深的万字Web基操文
isboyjc
2022/03/28
2.6K0
你真的了解跨域吗
一文带你了解跨域的前因后果和解决方案
在了解跨域之前,我们必须要了解一下同源策略。 跨域问题其实就是浏览器的同源策略造成的。
用户6297767
2023/12/23
5270
一文带你了解跨域的前因后果和解决方案
滴滴前端二面高频面试题合集
CORS需要浏览器和服务器同时支持,整个CORS过程都是浏览器完成的,无需用户参与。因此实现CORS的关键就是服务器,只要服务器实现了CORS请求,就可以跨源通信了。
aync_sync
2023/02/24
1.2K0
JS 跨域问题常见的五种解决方式
要理解跨域问题,就先理解好概念。跨域问题是由于javascript语言安全限制中的同源策略造成的.
书童小二
2018/09/03
1.8K0
JS 跨域问题常见的五种解决方式
WEB 前端跨域解决方案
2.) 资源嵌入: <link> 、 <script> 、 <img/> 、 <frame> 等 dom 标签,还有样式中 background:url() 、 @font-face() 等文件外链
chuchur
2022/10/25
1K0
这次全了,8种超详细Web跨域解决方案!
导语 | 在日常开发过程中,我们通常都会遇到ajax跨域请求或者前端跨域通信的开发场景。无论是前端同学还是后端同学都需要具备解决跨域问题的能力。本文总结梳理了常见的跨域场景、跨域解决方案及其优缺点,希望可以作为大家解决跨域问题的参考。 一、什么是跨域 当a.qq.com域名下的页面或脚本试图去请求b.qq.com域名下的资源时,就是典型的跨域行为。跨域的定义从受限范围可以分为两种,广义跨域和狭义跨域。 (一)广义跨域 广义跨域通常包含以下三种行为: 资源跳转:a链接、重定向。 资源嵌入:<li
腾讯云开发者
2021/10/11
5.4K0
那些年前端跨过的域
同源策略(same-origin policy) 最初是由 Netspace 公司在 1995 年引入浏览器的一种安全策略,现在所有的浏览器都遵守同源策略,它是浏览器安全的基石。
沃趣科技
2018/05/15
2.1K1
那些年前端跨过的域
什么是跨域?解决方案有哪些?
同源策略/SOP(Same origin policy)是一种约定,由Netscape公司1995年引入浏览器,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,浏览器很容易受到XSS、CSFR等攻击。所谓同源是指"协议+域名+端口"三者相同,即便两个不同的域名指向同一个ip地址,也非同源。
用户1093975
2018/08/03
15.3K0
什么是跨域?解决方案有哪些?
跨域分析以及通解
现今绝大多数新上线的网站都是基于前后端分离的部署模式来对外提供服务,而这种模式在不熟悉的情况下就很容易遇到一个恶心的问题——跨域
Yerik
2022/05/01
1.3K0
10 种跨域解决方案(附终极方案)
嗯。又来了,又说到跨域了,这是一个老生常谈的话题,以前我觉得这种基础文章没有什么好写的,会想着你去了解底层啊,不是很简单吗。但是最近在开发一个 「vscode 插件」 发现,当你刚入门一样东西的时候,你不会想这么多,因为你对他不熟悉,当你遇到不会的东西,你就是想先找到解决方案,然后通过这个解决方案再去深入理解。就比如跨域,新人或者刚接触的人对它并不是那么熟悉,所以说列出一些自己积累的方案,以及一些常用的场景来给他人带来一些解决问题的思路,这件事是有意义的。(写完之后还发现真香。以后忘了还能回来看看)
ConardLi
2020/05/08
3.2K0
10 种跨域解决方案(附终极方案)
AJAX 与跨域通信(二):跨域解决方案
本篇讲解常见的几种跨域方案:JSONP、CORS、图像Ping、document.domain、window.name。
Chor
2019/11/11
1.5K0
AJAX 与跨域通信(二):跨域解决方案
ajax实现跨域_js跨域请求的三种方法
跨域大家都知道,不同地址,不同端口,不同级别,不同协议都会构成跨域。例如:about.haorooms.com和www.haorooms.com都会构成跨域。总结起来只要协议、域名、端口有任何一个不同,都被当作是不同的域。下面举例,每两个一组。
全栈程序员站长
2022/09/23
3.2K0
前后端数据交互(七)——前端跨域解决方案(全)
同源策略(SOP)是一种约定,是浏览器最核心的也是最基本的安全功能,如果缺少了同源策略,浏览器很容易受到 XSS、CSFR等攻击。
呆呆
2021/12/01
5940
相关推荐
10 种CORS跨域解决方案
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档