لماذا باستخدام جافا سكريبت eval وظيفة فكرة سيئة ؟

StackOverflow https://stackoverflow.com/questions/86513

  •  01-07-2019
  •  | 
  •  

سؤال

التقييم وظيفة هي قوية وسهلة حيوي توليد رمز ، فما هي المحاذير?

هل كانت مفيدة؟

المحلول

  1. سوء استخدام eval يفتح الخاصة بك رمز هجمات حقن

  2. التصحيح يمكن أن يكون أكثر صعوبة (لا توجد أرقام الأسطر ، إلخ.)

  3. eval ان التعليمات البرمجية أبطأ (أي فرصة تجميع/ذاكرة التخزين المؤقت eval ان رمز)

تحرير:كما @جيف الدن نقطة في التعليقات #3 هو أقل صحيحا اليوم مما كان عليه في عام 2008.ومع ذلك ، في حين أن بعض التخزين المؤقت من النصوص المترجمة قد يحدث هذا ستقتصر فقط على النصوص التي eval أن تتكرر مع أي تعديل.إن السيناريو الأرجح هو أن يتم التقييم التعرف على النصوص التي خضعت تعديل طفيف في كل مرة وعلى هذا النحو لا يمكن أن يكون مؤقتا.دعنا نقول فقط أن بعض eval ان التعليمات البرمجية ببطء أكثر.

نصائح أخرى

eval ليس دائما الشر.هناك أوقات حيث أنه من المناسب تماما.

ومع ذلك, eval حاليا وتاريخيا على نطاق واسع المستخدمة من قبل الناس الذين لا يعرفون ماذا يفعلون.التي تشمل الناس كتابة سكريبت الدروس, للأسف, في بعض الحالات وهذا يمكن أن يكون في الواقع العواقب الأمنية أو أكثر في كثير من الأحيان بسيطة البق.لذلك يمكننا فعله لرمي علامة استفهام على eval أفضل.في أي وقت يمكنك استخدام eval تحتاج إلى التعقل-تحقق ما تفعله لأن هناك احتمالات يمكن أن تفعل ذلك أفضل وأكثر أمنا ونظافة الطريق.

لإعطاء جميع-أيضا-مثال نموذجي ، لتعيين لون أي عنصر معرف المخزنة في المتغير 'البطاطس':

eval('document.' + potato + '.style.color = "red"');

وإذا كان أصحاب هذا النوع من التعليمات البرمجية أعلاه فكرة عن أساسيات كيفية كائنات جافا سكريبت العمل, وكانوا قد أدركت أن بين معقوفتين يمكن أن تستخدم بدلا من حرفية دوت أسماء تنتفي الحاجة eval:

document[potato].style.color = 'red';

...والتي هي أسهل بكثير من قراءة وكذلك أقل يحتمل أن تكون عربات التي تجرها الدواب.

(ولكن إذا شخص /حقا/ يعرفون ما كانوا يفعلون يقول:

document.getElementById(potato).style.color = 'red';

الذي هو أكثر موثوقية من المراوغة الخدعة القديمة من الوصول إلى عناصر DOM مباشرة من كائن المستند.)

أعتقد لأنه يمكن تنفيذ أي وظيفة جافا سكريبت من سلسلة.باستخدام هذا يجعل من الأسهل على الناس أن حقن المارقة البرمجية في التطبيق.

نقطتين تتبادر إلى الذهن:

  1. الأمن (ولكن طالما يمكنك توليد السلسلة إلى تقييم نفسك, قد يكون هذا غير قضية)

  2. الأداء:حتى رمز إلى أن أعدم هو معروف, فإنه لا يمكن أن يكون الأمثل.(عن جافا سكريبت و الأداء, بالتأكيد ستيف Yegge عرض)

يمر إدخال المستخدم إلى eval() هو خطر أمني ، ولكن أيضا كل الاحتجاج eval() بإنشاء مثيل جديد من مترجم جافا سكريبت.هذا يمكن أن يكون مورد خنزير.

عموما المشكلة فقط إذا كنت تمر eval إدخال المستخدم.

أساسا ، فإنه من الصعب للحفاظ على التصحيح.انها مثل goto.يمكنك استخدامه ، ولكن ذلك يجعل من الصعب أن تجد مشاكل من الصعب على الناس الذين قد تحتاج إلى إجراء تغييرات في وقت لاحق.

شيء واحد أن نأخذ في الاعتبار هو أنه يمكنك في كثير من الأحيان استخدام eval() إلى تنفيذ التعليمات البرمجية في غير ذلك المقيد البيئة - مواقع الشبكات الاجتماعية أن كتلة محددة وظائف جافا سكريبت يمكن في بعض الأحيان ينخدع كسر لهم في eval كتلة

eval('al' + 'er' + 't(\'' + 'hi there!' + '\')');

حتى إذا كنت تبحث عن تشغيل بعض شفرة جافا سكريبت التي قد لا يكون خلاف ذلك يسمح (ماي سبيس, أنا أنظر إليك...) ثم eval() يمكن أن يكون خدعة مفيدة.

ومع ذلك ، بالنسبة لجميع الأسباب المذكورة أعلاه لا يجب استخدام التعليمات البرمجية الخاصة بك حيث يكون لديك سيطرة كاملة - أنه ليس من الضروري ، أفضل حالا هبط إلى 'صعبة جافا سكريبت الخارقة' الجرف.

إلا إذا كنت اسمحوا eval() a المحتوى الديناميكي (عن طريق cgi أو المدخلات) ، فمن آمن و الصلبة الأخرى جافا سكريبت في الصفحة الخاصة بك.

جنبا إلى جنب مع بقية الأجوبة لا أعتقد eval البيانات يمكن أن يكون المتقدم إلى أدنى حد ممكن.

فمن الممكن المخاطر الأمنية ، مختلفة نطاق التنفيذ ، و هي جدا فعالة ، كما أنه يخلق جديد تماما بيئة البرمجة من أجل تنفيذ التعليمات البرمجية.انظر هنا للحصول على المزيد من المعلومات: eval.

ومن المفيد جدا, على الرغم من استخدامها مع الاعتدال يمكن أن تضيف الكثير من وظيفة جيدة.

إلا إذا كنت متأكد 100% أن قانون يجري تقييمها من مصدر موثوق به (عادة التطبيق الخاص بك) ثم انها وسيلة مؤكدة النجاح من فضح النظام الخاص بك إلى البرمجة عبر الموقع الهجوم.

أعرف أن هذا النقاش هو قديم ولكن أنا حقا مثل هذا نهج جوجل و أردت أن أشارك في هذا الشعور مع الآخرين؛)

والشيء الآخر هو أن تحصل على أفضل وكلما حاول أن تفهم و أخيرا كنت لا أعتقد أن شيئا ما هو جيدة أو سيئة فقط لأن أحدهم قال ذلك :) هذه هي ملهمة جدا فيديو التي ساعدتني على التفكير أكثر من نفسي :) الممارسات الجيدة هي جيدة ولكن لا تستخدم لهم mindelessly :)

انها ليست بالضرورة سيئة المقدمة تعرف ماذا سياق كنت استخدامه في.

إذا كان التطبيق الخاص بك يستخدم eval() لإنشاء كائن من بعض JSON التي قد عاد من مدعوم إلى الموقع الخاص بك, التي أنشأتها الخاص بك موثوق بها تعليمات برمجية من جانب الخادم ، ربما لا مشكلة.

غير موثوق بها من جانب العميل كود جافا سكريبت لا تستطيع أن تفعل ذلك كثيرا على أي حال.قدمت شيء أنت المنفذة eval() على من المعقول المصدر, أنت بخير.

فإنه يقلل إلى حد كبير مستوى الثقة عن الأمن.

إذا كنت تريد من المستخدم إدخال بعض الدالات المنطقية و تقييم و أو جافا سكريبت eval وظيفة مثالية.أنا لا يمكن أن يقبل سلسلتين ، eval(uate) string1 === string2, ، وما إلى ذلك.

إذا كنت بقعة استخدام eval() في التعليمات البرمجية الخاصة بك ، تذكر شعار "eval() هو الشر".

هذا الدالة تأخذ التعسفي سلسلة ينفذ على أنها شفرة جافا سكريبت.عندما البرمجية في السؤال هو معروف مسبقا (لا تحديد في وقت التشغيل) لا يوجد سبب لاستخدام eval().إذا التعليمات البرمجية التي تم إنشاؤها بشكل حيوي في وقت التشغيل, هناك كثير من الأحيان أفضل وسيلة تحقيق الهدف دون eval().على سبيل المثال, فقط باستخدام قوس مربع التدوين الوصول إلى خصائص ديناميكية أفضل و أبسط:

// antipattern
var property = "name";
alert(eval("obj." + property));

// preferred
var property = "name";
alert(obj[property]);

باستخدام eval() أيضا له تداعيات أمنية ، لأنه قد يكون تنفيذ التعليمات البرمجية (على مثال القادمة من الشبكة) التي تم العبث بها.هذا هو مشترك antipattern عند التعامل مع JSON استجابة من طلب اياكس.في تلك الحالات فإنه من الأفضل استخدام المتصفحات' المدمج في أساليب تحليل سلمان استجابة جعل متأكد من انها آمنة و صالحة.لمتصفحات التي لا تدعم JSON.parse() أصلا, يمكنك استخدام المكتبة من JSON.org.

من المهم أيضا أن نتذكر أن يمر سلاسل setInterval(), setTimeout(), و Function() منشئ هو, بالنسبة للجزء الأكبر, مماثلة باستخدام eval() وبالتالي وينبغي تجنبها.

وراء الكواليس, جافا سكريبت لا يزال لديه لتقييم وتنفيذ سلسلة تمرير مثل كود البرمجة:

// antipatterns
setTimeout("myFunc()", 1000);
setTimeout("myFunc(1, 2, 3)", 1000);

// preferred
setTimeout(myFunc, 1000);
setTimeout(function () {
myFunc(1, 2, 3);
}, 1000);

باستخدام وظيفة جديدة() منشئ مشابه eval() وينبغي أن اقترب مع الرعاية.أنها يمكن أن تكون قوة بناء ، لكن غالبا ما يساء استخدامها.إذا كنت على الاطلاق ويجب استخدام eval(), يمكنك أن تنظر في استخدام وظيفة جديدة() بدلا من ذلك.

هناك الصغيرة المحتملة فائدة لأن رمز تقييمها في وظيفة جديدة() سوف تكون قيد التشغيل في الوظيفة نطاق ، حتى أي متغيرات محددة مع فار في قانون يجري تقييمها لن تصبح globals تلقائيا.

هناك طريقة أخرى لمنع التلقائي جلوبل هو التفاف eval() الاتصال في فورية وظيفة.

إلى جانب القضايا الأمنية المحتملة إذا تم تنفيذ المقدم المستخدم رمز معظم الوقت هناك طريقة أفضل من أن لا تنطوي على إعادة تحليل التعليمات البرمجية في كل مرة يعدم.مجهول وظائف أو خصائص الكائن يمكن أن يحل محل معظم الاستخدامات eval و أكثر أمانا وأسرع.

هذا قد تصبح أكثر من قضية الجيل القادم من متصفحات يخرج مع بعض نكهة جافا سكريبت مترجم.التعليمات البرمجية التي يتم تنفيذها عبر Eval قد لا تؤدي وكذلك بقية جافا سكريبت الخاصة بك ضد أحدث المتصفحات.شخص ما يجب أن تفعل بعض التنميط.

هذا هو واحد من مقالات جيدة تتحدث عن eval وكيف أنها ليست شريرة:http://www.nczonline.net/blog/2013/06/25/eval-isnt-evil-just-misunderstood/

أنا لا أقول يجب أن تذهب إلى البدء في استخدام eval() في كل مكان.في الواقع, هناك عدد قليل جدا من حالات استخدام جيد لتشغيل eval() على الإطلاق.بالتأكيد هناك مخاوف مع رمز الوضوح ، debugability ، وبالتأكيد الأداء التي ينبغي عدم إغفالها.ولكن يجب أن لا تخافوا على استخدامه عندما يكون لديك حالة eval() معنى.حاول أن لا تستخدم لأول مرة, ولكن لا تدع أي شخص يخيف كنت أفكر في التعليمات البرمجية الخاصة بك أكثر هشاشة أو أقل أمنا عندما eval() يتم استخدامها بشكل مناسب.

eval() هي قوية جدا ويمكن استخدامها لتنفيذ شبيبة بيان أو تقييم تعبير.ولكن السؤال ليس عن استخدامات eval() ولكن دعنا نقول فقط بعض كيف السلسلة تركض مع eval() يتأثر طرف الخبيثة.في النهاية سوف يتم تشغيل التعليمات البرمجية الضارة.مع السلطة تأتي المسؤولية.حتى استخدامها بحكمة هو استخدامك له.هذا لا علاقة الكثير eval() وظيفة ولكن هذه المادة جيدة المعلومات: http://blogs.popart.com/2009/07/javascript-injection-attacks/ إذا كنت تبحث عن أساسيات eval() انظر هنا:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval

أنا لن محاولة لدحض أي شيء قال: حتى الآن, ولكن سوف نقدم هذا الاستخدام eval() أن (بقدر ما أعرف) لا يمكن أن يتم بأي طريقة أخرى.ربما هناك طرق أخرى رمز هذا ، وربما طرق لتحسين ذلك ، ولكن يتم ذلك تخفف ودون أي أجراس وصفارات من أجل الوضوح أجل لتوضيح استخدام eval حقا لا تملك أي بدائل أخرى.وهذا هو:الديناميكية (أو بدقة أكثر) programmically إنشاء كائن أسماء (بدلا من القيم).

//Place this in a common/global JS lib:
var NS = function(namespace){
    var namespaceParts = String(namespace).split(".");
    var namespaceToTest = "";
    for(var i = 0; i < namespaceParts.length; i++){
        if(i === 0){
            namespaceToTest = namespaceParts[i];
        }
        else{
            namespaceToTest = namespaceToTest + "." + namespaceParts[i];
        }

        if(eval('typeof ' + namespaceToTest) === "undefined"){
            eval(namespaceToTest + ' = {}');
        }
    }
    return eval(namespace);
}


//Then, use this in your class definition libs:
NS('Root.Namespace').Class = function(settings){
  //Class constructor code here
}
//some generic method:
Root.Namespace.Class.prototype.Method = function(args){
    //Code goes here
    //this.MyOtherMethod("foo"));  // => "foo"
    return true;
}


//Then, in your applications, use this to instantiate an instance of your class:
var anInstanceOfClass = new Root.Namespace.Class(settings);

تحرير:بالمناسبة, أنا لن أقترح (لجميع لأسباب أمنية أشارت حتى الآن) أن قاعدة لك أسماء الكائنات على مدخلات المستخدم.لا أستطيع أن أتخيل أي سبب وجيه كنت تريد أن تفعل ذلك على الرغم من.لا يزال فكرت الإشارة إلى أنه لن يكون فكرة جيدة :)

جافا سكريبت محرك يحتوي على عدد من تحسينات الأداء التي ينفذ خلال تجميع المرحلة.بعض هذه تختزل إلى كونها قادرة على الأساس ثابت تحليل التعليمات البرمجية كما lexes ، قبل تحديد أين كل متغير وظيفة الإعلانات ، بحيث يستغرق أقل جهد لحل معرفات أثناء التنفيذ.

ولكن إذا كان المحرك يجد eval(..) في القانون, وهو في الأساس يجب أن نفترض أن كل الوعي معرف الموقع قد يكون غير صحيح, لأنه لا يعرف في lexing الوقت بالضبط ما البرمجية التي قد تمر على eval(..) تعديل المعجمية نطاق أو محتويات الكائن قد تمر مع خلق جديد المعجمية نطاق استشارتها.

وبعبارة أخرى, في التشاؤم المعنى ، معظم هذه التحسينات سيكون بلا فائدة إذا eval(..) هو الحاضر ، لذلك فإنه ببساطة لا تؤدي التحسينات في كل شيء.

هذا يفسر كل شيء.

المرجع :

https://github.com/getify/You-Dont-Know-JS/blob/master/scope%20&%20closures/ch2.md#eval

https://github.com/getify/You-Dont-Know-JS/blob/master/scope%20&%20closures/ch2.md#performance

انها ليست دائما فكرة سيئة.خذ على سبيل المثال مدونة جيل.لقد كتبت مؤخرا مكتبة تسمى Hyperbars الذي يسد الفجوة بين الظاهري دوم و المقاود.وذلك من خلال تحليل مجموعة المقاود قالب وتحويلها إلى hyperscript والتي تستخدم في وقت لاحق من قبل الظاهري-دوم.على hyperscript هو إنشاء سلسلة أولا و قبل عودته ، eval() ذلك أن تتحول إلى قانون قابل للتنفيذ.لقد وجدت eval() في هذه الحالة بالذات على العكس تماما من الشر.

أساسا من

<div>
    {{#each names}}
        <span>{{this}}</span>
    {{/each}}
</div>

هذا

(function (state) {
    var Runtime = Hyperbars.Runtime;
    var context = state;
    return h('div', {}, [Runtime.each(context['names'], context, function (context, parent, options) {
        return [h('span', {}, [options['@index'], context])]
    })])
}.bind({}))

أداء eval() ليست قضية في موقف مثل هذا لأنك تحتاج فقط إلى تفسير السلسلة التي تم إنشاؤها مرة واحدة ثم إعادة الملف التنفيذي الناتج عدة مرات.

يمكنك أن ترى كيفية إنشاء رمز تحقق إذا كنت غريبة هنا.

وأود أن أذهب إلى حد القول أنه لا يهم حقا إذا كنت تستخدم eval() في جافا سكريبت التي تعمل في المتصفحات.*(التحذير)

جميع المتصفحات الحديثة لديها وحدة التحكم المطور حيث يمكنك تنفيذ التعسفي جافا سكريبت على أي حال و أي شبه الذكي المطور يمكن أن ننظر في شبيبة المصدر و وضع كل ما بت من ذلك أنهم بحاجة إلى ديف تحكم على فعل ما يحلو لهم.

*طالما الخادم الخاص بك النهاية الصحيحة التحقق من الصحة & الحذف من المستخدم تزويد القيم, يجب أن لا يهم ما يحصل تحليل و eval كنت في جافا سكريبت العميل.

إذا كنت تسأل إذا هو مناسب أن يستعمل eval() في PHP ومع ذلك ، فإن الجواب هو لا, إلا إذا القائمة البيضاء أي القيم التي قد تكون مرت بك eval البيان.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top