เรียกใช้งานโค้ด JavaScript ที่จัดเก็บเป็นสตริง


173

ฉันจะรัน JavaScript บางตัวที่เป็นสตริงได้อย่างไร

function ExecuteJavascriptString()
{
    var s = "alert('hello')";
    // how do I get a browser to alert('hello')?
}

คำตอบ:


227

ด้วยeval("my script here")ฟังก์ชั่น


11
ระวัง ! นี่จะรันโค้ดดังนั้นระวังที่ / วิธีที่คุณได้รับสายนี้ โปรดทราบว่าทุกคนอาจพยายามใส่รหัสที่เป็นอันตรายในสายอักขระ
Jon

@divinci สิ่งนี้เรียกว่า "Cross Site Scripting" ดูที่นี่: en.wikipedia.org/wiki/Cross-site_scripting
Brendon Shaw

134

คุณสามารถรันมันด้วยฟังก์ชั่น ตัวอย่าง:

var theInstructions = "alert('Hello World'); var x = 100";

var F=new Function (theInstructions);

return(F());

3
แต่ในที่สุด - มันไม่เหมือนกับการโทรvar F=function(){eval(theInstructions);};หรือเปล่า
Jörn Berkefeld

14
ใช่และไม่ใช่: ด้วยรหัส eval จะถูกดำเนินการในขณะที่มีรหัส Function () ไม่ทำงานจนกว่า F () (ใช้ case? ตรวจสอบข้อผิดพลาดทางไวยากรณ์ แต่ไม่ต้องการรันโค้ด)
G3z

2
@stefan It's beatifull ...new Function("alert('Hello World');")()
Andrés Morales

ฉันลองสิ่งนี้ภายในบล็อกลอง / จับและทำงานได้อย่างสมบูรณ์ ตอนนี้ฉันสามารถนำโค้ด JavaScript ใด ๆ ที่พิมพ์ลงในบล็อกข้อความส่งผ่านไปยังฟังก์ชั่นของฉันและดำเนินการได้ บล็อก catch สามารถแทรกข้อความแสดงข้อผิดพลาดจากเอ็นจิน JavaScript ลงในองค์ประกอบ DOM และแสดงข้อผิดพลาดใด ๆ ในโค้ด หากมีคนต้องการฟังก์ชั่นที่ฉันเขียนเมื่อฉันจัดระเบียบมันแล้วฉันสามารถโพสต์ได้ที่นี่
David Edwards

@DavidEdwards จะยอดเยี่ยมถ้าคุณยังมีและโพสต์
Anoop

60

evalฟังก์ชั่นจะประเมินสตริงที่ส่งผ่านไปมัน

แต่การใช้งานevalอาจเป็นอันตรายดังนั้นควรใช้ด้วยความระมัดระวัง

แก้ไข: annakata มีจุดดี - ไม่เพียง แต่เป็นeval อันตรายก็เป็น ช้า นี่เป็นเพราะรหัสที่จะประเมินจะต้องมีการแยกวิเคราะห์ในจุดที่จะใช้ทรัพยากรการคำนวณบางอย่าง


34
สุดอันตรายและช้า - คุณควรตัวหนาตัวเอียงขีดเส้นใต้และ h1 ว่า
annakata

5
ฉันสงสัยว่ามันช้ากว่าการโหลด JavaScript ที่ใดก็ได้บนหน้าเว็บซึ่งจะต้องมีการแยกวิเคราะห์เช่นกัน หากช้ากว่าก็เป็นเพราะมันทำในขอบเขตที่แตกต่างกันซึ่งอาจบังคับให้สร้างทรัพยากรสำหรับขอบเขตนั้น
cgp

6
หากพูดว่าeval()อันตราย มีทางเลือกอื่นอีกไหม?
white_gecko

4
@coobird ฉันรู้ว่ามันสายไปหน่อย แต่ทำไมมันถึงอันตราย? ผู้ใช้สามารถเรียกใช้รหัส JavaScript บนเว็บไซต์ของคุณโดยใช้คอนโซล
jkd

7
หากการรักษาความปลอดภัยของคุณขึ้นอยู่กับจาวาสคริปต์ฝั่งไคลเอ็นต์คุณจะเสียเวลาไปอย่างมากและไม่มีอะไรเกี่ยวข้องกับ eval
Matthew

20

ใช้ eval ()

ทัวร์ W3 ของโรงเรียน evalEVAL ไซต์มีตัวอย่าง eval ที่ใช้งานได้ เอกสาร Mozilla ครอบคลุมรายละเอียดนี้

คุณอาจได้รับคำเตือนมากมายเกี่ยวกับการใช้สิ่งนี้อย่างปลอดภัย ไม่อนุญาตให้ผู้ใช้ฉีดสิ่งใดก็ตามลงใน eval ()เนื่องจากเป็นปัญหาด้านความปลอดภัยขนาดใหญ่

นอกจากนี้คุณยังจะต้องการที่จะรู้ว่า EVAL () มีความแตกต่างกันขอบเขต


11
w3fools.com W3C ไม่ได้มีอะไรจะพูดเกี่ยวกับการพัฒนา หากคุณต้องการเชื่อมโยงไปยังสิ่งที่เป็นทางการให้กำหนดเป้าหมายecma-international.org/ecma-262/5.1/#sec-15.1.2.1
Bergi

7
ฉันไม่ต้องการที่จะ "เชื่อมโยงไปยังสิ่งที่เป็นทางการฉันต้องการเชื่อมโยงไปยังสิ่งที่อ่านได้ - มองสิ่งที่คุณเชื่อมโยงมันไม่ได้ให้คำอธิบายว่ามีการใช้งานอย่างไรไม่มีตัวอย่างไม่มีทางคนจรจัดและอธิบายวิธีการแยก สำหรับผู้เริ่มต้นมันเป็นลิงค์ที่ไม่เหมาะสมอย่างสมบูรณ์เฮ้คุณจะไม่เกิดขึ้นกับ @bjorninge ใช่ไหม?
cgp

1
สเป็คอธิบายevalให้ฉันดีกว่าบทความ W3Schools บางสิ่งบางอย่างที่อ่านได้มีคำอธิบายที่ดีและตัวอย่างจะdeveloper.mozilla.org/en-US/docs/Web/JavaScript/Reference/... และไม่ฉันไม่ใช่ bjorninge
Bergi

ฉันจะยอมรับว่ามันไม่ใช่เอกสารประกอบและฉันจะยอมรับว่าหน้าของ mozilla นั้นเป็นภาพรวมที่ดีกว่า tweaked คำตอบของฉันเล็กน้อยตามความคิดเห็น
cgp

1
เกี่ยวกับลิงก์ ecma-international.org ฉันจะอธิบายว่าทุกคนสามารถอ่านและเห็นคุณค่าได้โดยมีประสบการณ์มากกว่า 15 นาทีกับ JS มันเป็นเรื่องดีมาก.
i336_

16

ลองสิ่งนี้:

  var script = "<script type='text/javascript'> content </script>";
  //using jquery next
  $('body').append(script);//incorporates and executes inmediatelly

โดยส่วนตัวฉันไม่ได้ทดสอบ แต่ดูเหมือนว่าจะทำงาน


1
คุณลืมหนีการปิด> ในสคริปต์: var script = "<script type = \" text / javascript \ "> เนื้อหา </ script \>";
rlib

1
ทำไมคุณต้องหนีจากการปิด>?
Jools

11

บิตเหมือนกับสิ่งที่@Hossein Hajizadeh กล่าวถึงแม้ว่าในรายละเอียดเพิ่มเติม

มีทางเลือกeval()คือ

ฟังก์ชั่น setTimeout()ถูกออกแบบมาเพื่อรันบางสิ่งหลังจากช่วงเวลาหนึ่งมิลลิวินาทีและรหัสที่จะดำเนินการจึงเกิดขึ้นเพื่อจัดรูปแบบเป็นสตริง

มันจะทำงานเช่นนี้:

ExecuteJavascriptString(); //Just for running it

function ExecuteJavascriptString()
{
    var s = "alert('hello')";
    setTimeout(s, 1);
}

1 หมายความว่ามันจะรอ 1 มิลลิวินาทีก่อนที่จะดำเนินการสตริง

มันอาจไม่ใช่วิธีที่ถูกต้องที่สุด แต่ก็ใช้งานได้


เสียหนึ่งมิลลิวินาทีทำไมเมื่อคุณสามารถส่งผ่าน 0 (ศูนย์) เพื่อsetTimeout? โปรดทราบว่าในกรณีใด ๆ มันจะทำให้การดำเนินการไม่ตรงกัน หมายความว่ารหัสทั้งหมดที่ตามหลังการsetTimeoutโทรจะถูกเรียกใช้ก่อนที่รหัสจะถูกส่งไปยังsetTimeout(แม้ว่าจะถูกเรียกด้วย 0 (ศูนย์))
jox

thought แค่คิดว่าอธิบายได้ดีขึ้นว่า setTimeout ทำงานอย่างไร
Anton Juul-Naber


7

ใช้evalดังนี้ ควรใช้ Eval ด้วยความระมัดระวังการค้นหาอย่างง่าย ๆ เกี่ยวกับ " eval is evil " ควรจะพอยน์เตอร์

function ExecuteJavascriptString()
{
    var s = "alert('hello')";
    eval(s);
}

2
คำแนะนำที่ดีเกี่ยวกับการค้นหาอย่างง่ายเกี่ยวกับ "eval is evil" ขอบคุณ!
Taptronic

5

ตรวจสอบเรื่องนี้กับสคริปต์ที่ซับซ้อนและยุ่งเหยิงมากมาย:

var js = "alert('Hello, World!');" // put your JS code here
var oScript = document.createElement("script");
var oScriptText = document.createTextNode(js);
oScript.appendChild(oScriptText);
document.body.appendChild(oScript);

5

หากคุณต้องการรันคำสั่งเฉพาะ (นั่นคือสตริง) หลังจากเวลาที่กำหนด - cmd = รหัสของคุณ - InterVal = หน่วงเวลาที่จะเรียกใช้

 function ExecStr(cmd, InterVal) {
    try {
        setTimeout(function () {
            var F = new Function(cmd);
            return (F());
        }, InterVal);
    } catch (e) { }
}
//sample
ExecStr("alert(20)",500);

@SteelBrain เพิ่มตัวอย่างที่รันโดย ExecStr ("alert (20)", 500);
Hossein Hajizadeh

1
ทำไมValในInterValตัวพิมพ์ใหญ่
โปรแกรม Redwolf

4

สำหรับผู้ใช้ที่กำลังใช้โหนดและมีความกังวลกับผลกระทบบริบทของeval()nodejs vmข้อเสนอ มันสร้างเครื่องเสมือน V8 ที่สามารถแซนด์บ็อกซ์ประมวลผลรหัสของคุณในบริบทที่แยกต่างหาก

การก้าวไปอีกขั้นหนึ่งเป็นเรื่องยากvm2ที่จะvmยอมให้ vm รันโค้ดที่ไม่น่าเชื่อถือ

const vm = require('vm');

const x = 1;

const sandbox = { x: 2 };
vm.createContext(sandbox); // Contextify the sandbox.

const code = 'x += 40; var y = 17;';
// `x` and `y` are global variables in the sandboxed environment.
// Initially, x has the value 2 because that is the value of sandbox.x.
vm.runInContext(code, sandbox);

console.log(sandbox.x); // 42
console.log(sandbox.y); // 17

console.log(x); // 1; y is not defined.

2
แทนที่จะพูดว่า "eval is evil" และไม่ให้บริบทหรือทางแก้ไขสิ่งนี้จริง ๆ แล้วพยายามแก้ไขปัญหา +1 สำหรับคุณ
โปรแกรม Redwolf

3
eval(s);

แต่สิ่งนี้อาจเป็นอันตรายได้หากคุณกำลังรับข้อมูลจากผู้ใช้แม้ว่าฉันคิดว่าพวกเขาทำผิดพลาดเบราว์เซอร์ของตัวเองนั่นเป็นปัญหาของพวกเขา


1
อย่างแน่นอน Eval นั้นอันตรายที่ฝั่งเซิร์ฟเวอร์ เกี่ยวกับลูกค้า ... ไม่มาก ผู้ใช้สามารถพิมพ์ javascript: someevilcode ในที่อยู่ของเบราว์เซอร์และบูม Eval อยู่ตรงนั้น
Esben Skov Pedersen

@EsbenSkovPedersen มีการป้องกันอย่างน้อยโครเมี่ยมและต้องมีการดำเนินการของผู้ใช้เมื่อเทียบกับไซต์ที่evalมีรหัสจากผู้ใช้ซึ่งอาจทำให้ผู้ใช้ขโมยบัญชีของผู้ใช้โดยที่พวกเขาไม่ทราบเพียงแค่โหลดหน้าเว็บ
1j01

1
@ 1j01 เพื่อความยุติธรรมความคิดเห็นของฉันคือห้าปี
Esben Skov Pedersen

@EsbenSkovPedersen นั่นเป็นเรื่องจริง :)
1j01

2

ไม่แน่ใจว่านี่เป็นการโกงหรือไม่:

window.say = function(a) { alert(a); };

var a = "say('hello')";

var p = /^([^(]*)\('([^']*)'\).*$/;                 // ["say('hello')","say","hello"]

var fn = window[p.exec(a)[1]];                      // get function reference by name

if( typeof(fn) === "function") 
    fn.apply(null, [p.exec(a)[2]]);                 // call it with params


2

ฉันกำลังตอบคำถามที่คล้ายกันและยังมีความคิดอื่นวิธีการบรรลุนี้โดยไม่ต้องใช้eval():

const source = "alert('test')";
const el = document.createElement("script");
el.src = URL.createObjectURL(new Blob([source], { type: 'text/javascript' }));
document.head.appendChild(el);

ในโค้ดข้างต้นคุณจะสร้าง Blob ซึ่งมีสคริปต์ของคุณเพื่อสร้าง URL ของวัตถุ (การแสดงของไฟล์หรือวัตถุ Blob ในหน่วยความจำเบราว์เซอร์) เนื่องจากคุณมีsrcคุณสมบัติบน<script>แท็กสคริปต์จะถูกดำเนินการเช่นเดียวกับถ้ามันถูกโหลดจาก URL อื่น ๆ


2
function executeScript(source) {
    var script = document.createElement("script");
    script.onload = script.onerror = function(){ this.remove(); };
    script.src = "data:text/plain;base64," + btoa(source);
    document.body.appendChild(script);
}

executeScript("alert('Hello, World!');");


0
eval(s);

โปรดจำไว้ว่า eval นั้นมีประสิทธิภาพมากและค่อนข้างไม่ปลอดภัย คุณควรมั่นใจว่าสคริปต์ที่คุณเรียกใช้นั้นปลอดภัยและไม่มีผู้ใช้ที่ไม่น่าเชื่อถือ


1
ใน JS ทุกอย่างสามารถเปลี่ยนแปลงได้โดยผู้ใช้เพียงพิมพ์ "javascript: document.write (" Hello World ");" ลงในแถบที่อยู่ของเบราว์เซอร์เกือบทุกชนิด
UnkwnTech

1
ใช่ แต่คุณสามารถทำให้มันยากขึ้นสำหรับเขาโดยไม่ใช้ตัวแปรทั่วโลก, ซ่อนฟังก์ชั่นของคุณในการปิด ฯลฯ นอกจากนี้โดยการหลีกเลี่ยง eval เช่นโรคระบาด =)
PatrikAkerstrand

0

หนึ่งสามารถใช้mathjs

ตัวอย่างจากลิงค์ด้านบน:

// evaluate expressions
math.evaluate('sqrt(3^2 + 4^2)')        // 5
math.evaluate('sqrt(-4)')               // 2i
math.evaluate('2 inch to cm')           // 5.08 cm
math.evaluate('cos(45 deg)')            // 0.7071067811865476

// provide a scope
let scope = {
    a: 3,
    b: 4
}
math.evaluate('a * b', scope)           // 12
math.evaluate('c = 2.3 + 4.5', scope)   // 6.8
scope.c                                

scopeเป็นวัตถุใด ๆ ดังนั้นหากคุณส่งขอบเขตทั่วโลกไปยังฟังก์ชันประเมินผลคุณอาจสามารถดำเนินการการแจ้งเตือน () แบบไดนามิกได้

mathjs ยังเป็นตัวเลือกที่ดีกว่า eval () เพราะมันทำงานในแซนด์บ็อกซ์

ผู้ใช้สามารถลองฉีดรหัส JavaScript ที่เป็นอันตรายผ่านตัวแยกวิเคราะห์นิพจน์ ตัวแยกวิเคราะห์นิพจน์ของ mathjs เสนอสภาพแวดล้อมแบบ sandbox เพื่อดำเนินการนิพจน์ซึ่งจะทำให้สิ่งนี้เป็นไปไม่ได้ เป็นไปได้ว่ามีช่องโหว่ด้านความปลอดภัยที่ไม่รู้จักดังนั้นจึงควรระมัดระวังโดยเฉพาะเมื่ออนุญาตให้มีการประมวลผลนิพจน์โดยพลการ

mathjs รุ่นใหม่กว่านี้ไม่ได้ใช้ eval () หรือ Function ()

parser ป้องกันการเข้าถึงจาวาสคริปต์ภายใน eval และ Function ใหม่ซึ่งเป็นสาเหตุหลักของการโจมตีด้านความปลอดภัย Mathjs เวอร์ชัน 4 และใหม่กว่าไม่ได้ใช้ eval ของ JavaScript ภายใต้ประทุน เวอร์ชัน 3 และเก่ากว่าใช้ eval สำหรับขั้นตอนการคอมไพล์ นี่ไม่ใช่ปัญหาด้านความปลอดภัยโดยตรง แต่ส่งผลให้พื้นผิวการโจมตีมีขนาดใหญ่ขึ้น


0

การใช้ทั้งการประเมินและการสร้างฟังก์ชั่นใหม่เพื่อรันจาวาสคริปต์นั้นมาพร้อมกับความเสี่ยงด้านความปลอดภัยจำนวนมาก

const script = document.createElement("script");
const stringJquery = '$("#button").on("click", function() {console.log("hit")})';
script.text = stringJquery;
document.body.appendChild(script);

ฉันชอบวิธีนี้ในการใช้งาน Javascript ที่ฉันได้รับเป็นสตริง

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.