最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

淺談Node.js 沙箱環(huán)境

 更新時(shí)間:2018年05月15日 09:31:42   作者:Randal  
本篇文章主要介紹了Node.js 沙箱環(huán)境 ,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧

node官方文檔里提到node的vm模塊可以用來(lái)做沙箱環(huán)境執(zhí)行代碼,對(duì)代碼的上下文環(huán)境做隔離。

\A common use case is to run the code in a sandboxed environment. The sandboxed code uses a different V8 Context, meaning that it has a different global object than the rest of the code.

先看一個(gè)例子

const vm = require('vm');
let a = 1;
var result = vm.runInNewContext('var b = 2; a = 3; a + b;', {a});
console.log(result);  // 5
console.log(a);     // 1
console.log(typeof b); // undefined

沙箱環(huán)境中執(zhí)行的代碼對(duì)于外部代碼沒(méi)有產(chǎn)生任何影響,無(wú)論是新聲明的變量b,還是重新賦值的變量a。 注意最后一行的代碼默認(rèn)會(huì)被加上return關(guān)鍵字,因此無(wú)需手動(dòng)添加,一旦添加的話不會(huì)靜默忽略,而是執(zhí)行報(bào)錯(cuò)。

const vm = require('vm');
let a = 1;
var result = vm.runInNewContext('var b = 2; a = 3; return a + b;', {a});
console.log(result);
console.log(a);
console.log(typeof b);

如下所示

evalmachine.<anonymous>:1
var b = 2; a = 3; return a + b;
         ^^^^^^

SyntaxError: Illegal return statement
  at new Script (vm.js:74:7)
  at createScript (vm.js:246:10)
  at Object.runInNewContext (vm.js:291:10)
  at Object.<anonymous> (/Users/xiji/workspace/learn/script.js:3:17)
  at Module._compile (internal/modules/cjs/loader.js:678:30)
  at Object.Module._extensions..js (internal/modules/cjs/loader.js:689:10)
  at Module.load (internal/modules/cjs/loader.js:589:32)
  at tryModuleLoad (internal/modules/cjs/loader.js:528:12)
  at Function.Module._load (internal/modules/cjs/loader.js:520:3)
  at Function.Module.runMain (internal/modules/cjs/loader.js:719:10)

除了runInNewContext外,vm還提供了runInThisContext和runInContext兩個(gè)方法都可以用來(lái)執(zhí)行代碼 runInThisContext無(wú)法指定context

const vm = require('vm');
let localVar = 'initial value';​
const vmResult = vm.runInThisContext('localVar += "vm";');
console.log('vmResult:', vmResult);
console.log('localVar:', localVar);
console.log(global.localVar);

由于無(wú)法訪問(wèn)本地的作用域,只能訪問(wèn)到當(dāng)前的global對(duì)象,因此上面的代碼會(huì)因?yàn)檎也坏絣ocalVal而報(bào)錯(cuò)

evalmachine.<anonymous>:1
localVar += "vm";
^

ReferenceError: localVar is not defined
  at evalmachine.<anonymous>:1:1
  at Script.runInThisContext (vm.js:91:20)
  at Object.runInThisContext (vm.js:298:38)
  at Object.<anonymous> (/Users/xiji/workspace/learn/script.js:3:21)
  at Module._compile (internal/modules/cjs/loader.js:678:30)
  at Object.Module._extensions..js (internal/modules/cjs/loader.js:689:10)
  at Module.load (internal/modules/cjs/loader.js:589:32)
  at tryModuleLoad (internal/modules/cjs/loader.js:528:12)
  at Function.Module._load (internal/modules/cjs/loader.js:520:3)
  at Function.Module.runMain (internal/modules/cjs/loader.js:719:10)

如果我們把要執(zhí)行的代碼改成直接賦值的話就可以正常運(yùn)行了,但是也產(chǎn)生了全局污染(全局的localVar變量)

const vm = require('vm');
let localVar = 'initial value';​
const vmResult = vm.runInThisContext('localVar = "vm";');
console.log('vmResult:', vmResult);  // vm
console.log('localVar:', localVar);  // initial value
console.log(global.localVar);     // vm

runInContext在傳入context參數(shù)上與runInNewContext有所區(qū)別 runInContext傳入的context對(duì)象不為空而且必須是經(jīng)vm.createContext()處理過(guò)的,否則會(huì)報(bào)錯(cuò)。 runInNewContext的context參數(shù)是非必須的,而且無(wú)需經(jīng)過(guò)vm.createContext處理。 runInNewContext和runInContext因?yàn)橛兄付╟ontext,所以不會(huì)向runInThisContext那樣產(chǎn)生全局污染(不會(huì)產(chǎn)生全局的localVar變量)

const vm = require('vm');
let localVar = 'initial value';​
const vmResult = vm.runInNewContext('localVar = "vm";');
console.log('vmResult:', vmResult);  // vm
console.log('localVar:', localVar);  // initial value
console.log(global.localVar);     // undefined

當(dāng)需要一個(gè)沙箱環(huán)境執(zhí)行多個(gè)腳本片段的時(shí)候,可以通過(guò)多次調(diào)用runInContext方法但是傳入同一個(gè)vm.createContext()返回值實(shí)現(xiàn)。

超時(shí)控制及錯(cuò)誤捕獲

vm針對(duì)要執(zhí)行的代碼提供了超時(shí)機(jī)制,通過(guò)指定timeout參數(shù)即可以runInThisContext為例

const vm = require('vm');
let localVar = 'initial value';​
const vmResult = vm.runInThisContext('while(true) { 1 }; localVar = "vm";', { timeout: 1000});
vm.js:91
   return super.runInThisContext(...args);
          ^

Error: Script execution timed out.
  at Script.runInThisContext (vm.js:91:20)
  at Object.runInThisContext (vm.js:298:38)
  at Object.<anonymous> (/Users/xiji/workspace/learn/script.js:3:21)
  at Module._compile (internal/modules/cjs/loader.js:678:30)
  at Object.Module._extensions..js (internal/modules/cjs/loader.js:689:10)
  at Module.load (internal/modules/cjs/loader.js:589:32)
  at tryModuleLoad (internal/modules/cjs/loader.js:528:12)
  at Function.Module._load (internal/modules/cjs/loader.js:520:3)
  at Function.Module.runMain (internal/modules/cjs/loader.js:719:10)
  at startup (internal/bootstrap/node.js:228:19)


可以通過(guò)try catch來(lái)捕獲代碼錯(cuò)誤

const vm = require('vm');
let localVar = 'initial value';​
try { 
  const vmResult = vm.runInThisContext('while(true) { 1 }; localVar = "vm";', {
    timeout: 1000
  });
} catch(e) { 
  console.error('executed code timeout');
}

延遲執(zhí)行

vm除了即時(shí)執(zhí)行代碼之外,也可以先編譯然后過(guò)一段時(shí)間再執(zhí)行,這就需要提到vm.Script了。其實(shí)無(wú)論是runInNewContext、runInThisContext還是runInThisContext,背后其實(shí)都創(chuàng)建了Script,從之前的報(bào)錯(cuò)信息就可以看出來(lái) 接下來(lái)我們就用vm.Script來(lái)重寫(xiě)本文開(kāi)頭的例子

const vm = require('vm');
let a = 1;
var script = new vm.Script('var b = 2; a = 3; a + b;');
setTimeout(() => { 
  let result = script.runInNewContext({a}); 
  console.log(result);   // 5 
  console.log(a);     // 1 
  console.log(typeof b);  // undefined
}, 300);

除了vm.Script,node在9.6版本中新增了vm.Module也可以做到延遲執(zhí)行,vm.Module主要用來(lái)支持ES6 module,而且它的context在創(chuàng)建的時(shí)候就已經(jīng)綁定好了,關(guān)于vm.Module目前還需要在命令行使用flag來(lái)啟用支持

node --experimental-vm-module index.js

vm作為沙箱環(huán)境安全嗎?

vm相對(duì)于eval來(lái)說(shuō)更安全一些,因?yàn)樗綦x了當(dāng)前的上下文環(huán)境了,但是盡管如此依然可以訪問(wèn)標(biāo)準(zhǔn)的JS API和全局的NodeJS環(huán)境,因此vm并不安全,這個(gè)在官方文檔里就提到了

The vm module is not a security mechanism. Do not use it to run untrusted code

請(qǐng)看下面的例子

const vm = require('vm');
vm.runInNewContext("this.constructor.constructor('return process')().exit()")
console.log("The app goes on...") // 永遠(yuǎn)不會(huì)輸出

為了避免上面這種情況,可以將上下文簡(jiǎn)化成只包含基本類(lèi)型,如下所示

let ctx = Object.create(null);
ctx.a = 1; // ctx上不能包含引用類(lèi)型的屬性
vm.runInNewContext("this.constructor.constructor('return process')().exit()", ctx);

針對(duì)原生vm存在的這個(gè)問(wèn)題,有人開(kāi)發(fā)了vm2包,可以避免上述問(wèn)題,但是也不能說(shuō)vm2就一定是安全的

const {VM} = require('vm2');
new VM().run('this.constructor.constructor("return process")().exit()');

雖然執(zhí)行上述代碼沒(méi)有問(wèn)題,但是由于vm2的timeout對(duì)于異步代碼不起作用,所以下面的代碼永遠(yuǎn)不會(huì)執(zhí)行結(jié)束。

const { VM } = require('vm2');
const vm = new VM({ timeout: 1000, sandbox: {}});
vm.run('new Promise(()=>{})');

即使希望通過(guò)重新定義Promise的方式來(lái)禁用Promise的話,還是一個(gè)可以繞過(guò)的

const { VM } = require('vm2');
const vm = new VM({ 
 timeout: 1000, sandbox: { Promise: function(){}}
});
vm.run('Promise = (async function(){})().constructor;new Promise(()=>{});');

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Windows系統(tǒng)下使用Sublime搭建nodejs環(huán)境

    Windows系統(tǒng)下使用Sublime搭建nodejs環(huán)境

    最近在研究Nodejs開(kāi)發(fā),俗話說(shuō),工欲善其事,必先利其器,當(dāng)然要找到一款用著順手的編輯器作為開(kāi)始。這里我們選擇的是Sublime Text 3,除了漂亮的用戶界面,最吸引我的就是它的插件擴(kuò)展功能以及跨平臺(tái)特性。
    2015-04-04
  • 利用Node轉(zhuǎn)換Excel成JSON的詳細(xì)步驟

    利用Node轉(zhuǎn)換Excel成JSON的詳細(xì)步驟

    最近工作中遇到一個(gè)需求,大致需求就是將Excel文件在導(dǎo)入時(shí)解析為json格式轉(zhuǎn)換數(shù)據(jù)結(jié)構(gòu)再傳輸給后臺(tái),下面這篇文章主要給大家介紹了關(guān)于如何利用Node轉(zhuǎn)換Excel成JSON的詳細(xì)步驟,需要的朋友可以參考下
    2022-11-11
  • pm2 部署 node的三種方法示例

    pm2 部署 node的三種方法示例

    本篇文章主要介紹了pm2 部署 node的三種方法示例,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-10-10
  • Node.js如何實(shí)現(xiàn)文件夾內(nèi)文件批量重命名

    Node.js如何實(shí)現(xiàn)文件夾內(nèi)文件批量重命名

    這篇文章主要為大家詳細(xì)介紹了Node.js如何實(shí)現(xiàn)文件夾內(nèi)文件批量重命名功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2025-03-03
  • node.js用fs.rename強(qiáng)制重命名或移動(dòng)文件夾的方法

    node.js用fs.rename強(qiáng)制重命名或移動(dòng)文件夾的方法

    本篇文章主要介紹了node.js用fs.rename強(qiáng)制重命名或移動(dòng)文件夾的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-12-12
  • NodeJS制作爬蟲(chóng)全過(guò)程(續(xù))

    NodeJS制作爬蟲(chóng)全過(guò)程(續(xù))

    本文是接上篇NodeJS制作爬蟲(chóng)全過(guò)程,是最上文的一個(gè)補(bǔ)充以及優(yōu)化,給需要的小伙伴參考下
    2014-12-12
  • Nodejs對(duì)postgresql基本操作的封裝方法

    Nodejs對(duì)postgresql基本操作的封裝方法

    今天小編就為大家分享一篇Nodejs對(duì)postgresql基本操作的封裝方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2019-02-02
  • Node.js使用Angular簡(jiǎn)單示例

    Node.js使用Angular簡(jiǎn)單示例

    這篇文章主要介紹了Node.js使用Angular簡(jiǎn)單示例,如何在Node.js項(xiàng)目中引入AngularJS,這次提供一個(gè)非常簡(jiǎn)單的示例,演示AngularJS里的指令、數(shù)據(jù)綁定、服務(wù)等內(nèi)容。感興趣的小伙伴們可以參考一下
    2018-05-05
  • npm鏡像源證書(shū)過(guò)期的問(wèn)題解決

    npm鏡像源證書(shū)過(guò)期的問(wèn)題解決

    因?yàn)閚pm官方鏡像在國(guó)內(nèi)訪問(wèn)很慢,我們基本上都會(huì)選擇切換到國(guó)內(nèi)的一些npm鏡像,本文主要介紹了npm鏡像源證書(shū)過(guò)期的問(wèn)題解決,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-07-07
  • NPM配置私服構(gòu)建內(nèi)網(wǎng)中央倉(cāng)庫(kù)過(guò)程詳解

    NPM配置私服構(gòu)建內(nèi)網(wǎng)中央倉(cāng)庫(kù)過(guò)程詳解

    這篇文章主要為大家介紹了NPM配置私服構(gòu)建內(nèi)網(wǎng)中央倉(cāng)庫(kù)過(guò)程詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08

最新評(píng)論

遵化市| 怀化市| 望江县| 平谷区| 民县| 渭南市| 景洪市| 丰台区| 临朐县| 佳木斯市| 乐安县| 八宿县| 阿克陶县| 凤山市| 涞水县| 安平县| 武川县| 北宁市| 天水市| 邮箱| 泸州市| 枝江市| 乐陵市| 南靖县| 泰州市| 贺州市| 襄城县| 林甸县| 徐闻县| 星子县| 崇礼县| 金溪县| 靖边县| 漯河市| 噶尔县| 肥城市| 正蓝旗| 上犹县| 宜昌市| 重庆市| 越西县|