沙箱机制sandbox

最近手头项目应用到了沙箱机制顺便研究了下 直接上代码~

function sandbox(code) {

    code= 'with (sandbox) {' + code + '}'

    return new Function('sandbox', code)

}

let str = 'let a = 10;console.log(a)'

sandbox(str)({})
//而es6的proxy则可以解决这个问题,proxy可以设置访问拦截器,于是with再加上proxy几乎完美解决js沙箱机制。当然,还是有机制可以绕过,有大神发现Symbol.unScopables可以不受with的影响,所以要另外处理Symbol.unScopables:
class ProxySandbox{
  constructor(){
    const rawWindow = window
    const fakeWindow = {}
    const proxy = new Proxy(fakeWindow, {
      set(target,prop,value){
        target[prop] = value
        return true
      },
      get(target,prop){
        return target[prop] || fakeWindow[prop]
      }
    })
    this.proxy = proxy
  }
}

const sandbox1 = new ProxySandbox()
const sandbox2 = new ProxySandbox()
window.a = 1
((window) => {
  window.a = 'hello'
  console.log(window.a)
})(sandbox1.proxy)
((window) => {
  window.a = 'world'
  console.log(window.a)
})(sandbox1.proxy)

上面的例子应用到es6的proxy,目前js沙箱能做到的最好的沙箱机制,适用于多个应用,但是也有兼容性的限制

快照沙箱

class snapShotSandbox{
  proxy = window // window 属性
  modifyPropsMap = {} // 记录在window上的修改
  active()
  active(){ // 激活沙箱
    this.windowSnapshot = {} // 拍照
    for(const prop in window){
      if(window.hasOwnProperty(prop)){
        this.windowSnapshot[prop] = window[prop]
      }
    }
    Object.keys(this.modifyPropsMap).forEach(prop => {
      window[prop] = this.modifyPropsMap[prop]
    })
  }
  inactive(){ // 失活沙箱
    for(const prop in window){
      if(window.hasOwnProperty(prop)){
        if(window[prop] !== this.windowSnapshot[prop]){
          this.modifyPropsMap[prop] = window[prop]
          window[prop] = this.windowSnapshot[prop]
        }
      }
    }
  }
}
const sandbox = new snapShotSandbox()
 
((window) => {
  window.a = 1
  window.b = 2
  console.log(window.a, window.b)
  sandbox.inactive()
  console.log(window.a, window.b)
  sandbox.active()
  console.log(window.a, window.b)
})(sandbox.proxy) // sandbox.proxy 就是 window

// 不支持多个子应用

你可能感兴趣的:(javascript)