iframe实现与父页面跨域隔离的JavaScript 代码沙箱

 更新时间:2023年05月16日 10:59:54   作者:知名喷子  
这篇文章主要介绍了使用iframe实现与父页面跨域隔离的JavaScript代码沙箱,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

正文

假如让你实现一个在线的 JavaScript 代码运行环境,要求用户代码不能对页面进行修改,以避免潜在的安全问题,你会怎么做?

使用 with?使用 proxy?OK ,都可以,但是这两种方法都需要关注很多细节,否则用户依旧有可乘之机,这样一来你的实现里面就会有一个很长长长长长长长的操作黑名单。

除此之外,我们还可以专门部署一个页面,将代码提到服务端渲染成页面,再通过 iframe 去访问,如果 iframe 与父页面之间是跨域的话可以达到很高的安全性——那么能不能不看后端的脸色,完全使用浏览器来实现类似的沙箱呢?

当然可以——

1. iframe

对前端页面而言,跨域是页面与页面之间的鸿沟,但这并不意味着我们必须重新打开一个页面来运行新的代码,因为我们可以使用 <iframe> 标签:

<iframe src="www.xxxx.xxx"></iframe>

对于同域的 iframe ,我们可以直接通过 .contentWindow 访问并操作它的全局对象,然后直接往里面执行 JavaScript:

document.querySelector('iframe')
  .contentWindow
  .eval('alert("hello world!");');

但是同域页面的子页面是可以与父页面进行互操作的,

2. data URL

你可能在一些页面里见过小图片不使用网络链接,而是采用一个 data:image/png;base64 xxxxxxx 风格的 URL ,这种 URL 就是 data URL


除了 data URL 之外你可能还见过 blob:// 开头的 URL —— Object URL。不过 Object URL 与当前页面是同域的,而 data URL 与当前页面是跨域的。所以我们可以在 iframe 使用 data URL 来进行跨域隔离

3. 将 JavaScript 代码变成 data URL

我们可以直接将 JavaScript 片段变成 data:application/javascript, 的 URL ,但是这样有一个问题: iframe 打开这样的 URL 的时候,会显示代码原文而不是执行代码,这个行为其实和你直接在浏览器地址栏输入 JS 的 URL 是一样的。
所以我们需要将 JavaScript 代码拼接到 html 里面,再变成 data URL ,然后交给 iframe 去加载:

const javaScriptFragment = `
alert('hello world');
`;
const htmlFragment = `
<!doctype html>
<html>
  <head>
    <meta chatset="utf-8" />
  </head>
  <body>
    <script>${javaScriptFragment}</script>
  </body>
</html>
`;
const dataUrl = `data:text/html,${htmlFragment}`;
// 注意,如果代码片段中含有中文的话,需要使用 encodeURIFragment 转义 htmlFragment
document.querySelector('iframe').src = dataUrl;

4. 如果需要获取执行结果的话,基于 postMessage 定制通信机制

如果我们不但要做沙箱隔离,还被要求获取运行结果的话,则可以做一个通信机制,让 iframe 获取到用户代码执行结果, iframe 与父页面之间最好的跨域通信方法莫过于 postMessage
除了获取结果之外,还可以将通信机制进一步扩展成为 RPC ,这样可以实时修改页面里的代码来查看效果,类似于 codepen 。

具体实现与主题不是强相关,这里就不写了,更多关于JavaScript iframe页面跨域隔离的资料请关注脚本之家其它相关文章!

相关文章

  • document.compatMode的CSS1compat使用介绍

    document.compatMode的CSS1compat使用介绍

    这篇文章主要介绍了document.compatMode的CSS1compat使用,需要的朋友可以参考下
    2014-04-04
  • 微信小程序页面间传值的实现方法示例

    微信小程序页面间传值的实现方法示例

    这篇文章主要给大家介绍了关于微信小程序页面间传值的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-04-04
  • 浅谈javascript函数式编程

    浅谈javascript函数式编程

    你是否知道JavaScript其实也是一个函数式编程语言呢?本文将教你如何利用JavaScript的函数式特性。
    2015-09-09
  • js实现上下左右弹框划出效果

    js实现上下左右弹框划出效果

    本文主要介绍js实现上下左右弹框划出效果的实例,具有很好的参考价值。下面跟着小编一起来看下吧
    2017-03-03
  • 浅谈js的ajax的异步和同步请求的问题

    浅谈js的ajax的异步和同步请求的问题

    下面小编就为大家带来一篇浅谈js的ajax的异步和同步请求的问题。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-10-10
  • 详解webpack中的hash、chunkhash、contenthash区别

    详解webpack中的hash、chunkhash、contenthash区别

    这篇文章主要介绍了详解webpack中的hash、chunkhash、contenthash区别,详细的介绍了hash、chunkhash、contenthash的用法和区别,有兴趣的可以了解一下
    2018-01-01
  • 基于BootStrap Metronic开发框架经验小结【七】数据的导入、导出及附件的查看处理

    基于BootStrap Metronic开发框架经验小结【七】数据的导入、导出及附件的查看处理

    在很多系统模块里面,我们可能都需要进行一定的数据交换处理,这样可以很好的达到用户操作体验感,接下来通过本文给大家介绍基于BootStrap Metronic开发框架经验小结【七】数据的导入、导出及附件的查看处理相关知识,非常具有参考价值,感兴趣的朋友一起学习吧
    2016-05-05
  • JavaScript 实现同时选取多个时间段的方法

    JavaScript 实现同时选取多个时间段的方法

    这篇文章主要介绍了JavaScript 实现同时选取多个时间段的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-10-10
  • codeMirror插件使用讲解

    codeMirror插件使用讲解

    codeMirror是一款十分强大的代码编辑插件,提供了十分丰富的API,最近在项目中用到了这款插件,于是在这里给大家分享下使用方法和心得。具有一定的参考价值,下面跟着小编一起来看下吧
    2017-01-01
  • 使用Js让Html中特殊字符不被转义

    使用Js让Html中特殊字符不被转义

    怎么让<textarea></textarea>之间包含的文本原封不动的显示出来呢?下面小编就为大家介绍一下具体的实现方法吧
    2013-11-11

最新评论