乐趣区

关于javascript:沙箱机制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

// 不反对多个子利用

退出移动版