javascript alternative - Perché utilizzare la funzione eval JavaScript è una cattiva idea?




13 Answers

  1. L'uso improprio di eval apre il tuo codice per gli attacchi di iniezione

  2. Il debugging può essere più impegnativo (nessun numero di linea, ecc.)

  3. il codice eval'd viene eseguito più lentamente (nessuna possibilità di compilare / memorizzare in cache il codice eval'd)

Edit: Come @Jeff Walden fa notare nei commenti, # 3 è meno vero oggi di quanto non fosse nel 2008. Tuttavia, mentre alcuni caching di script compilati possono accadere, questo sarà limitato agli script che sono stati eval'd ripetuti senza alcuna modifica. Uno scenario più probabile è che si stanno valutando script che hanno subito ogni volta piccole modifiche e che quindi non possono essere memorizzati nella cache. Diciamo solo che QUALSIASI codice eval'd viene eseguito più lentamente.

eval() nodejs

La funzione eval è un modo semplice e potente per generare dinamicamente il codice, quindi quali sono gli avvertimenti?




Credo che sia perché può eseguire qualsiasi funzione JavaScript da una stringa. Usarlo rende più facile per le persone iniettare il codice rogue nell'applicazione.




Passare l'input dell'utente a eval () è un rischio per la sicurezza, ma anche ogni chiamata di eval () crea una nuova istanza dell'interprete JavaScript. Questo può essere un vantaggio per le risorse.




Soprattutto, è molto più difficile da mantenere e eseguire il debug. È come un goto . Puoi usarlo, ma rende più difficile trovare problemi e più difficile con le persone che potrebbero aver bisogno di apportare modifiche in seguito.




A meno che tu non abbia reso eval () un contenuto dinamico (tramite cgi o input), è sicuro e solido come tutti gli altri JavaScript nella tua pagina.




È un possibile rischio per la sicurezza, ha un diverso ambito di esecuzione ed è piuttosto inefficiente, poiché crea un ambiente di scripting completamente nuovo per l'esecuzione del codice. Vedi qui per ulteriori informazioni: eval .

È abbastanza utile, tuttavia, e utilizzato con moderazione può aggiungere molte buone funzionalità.




So che questa discussione è vecchia, ma mi piace molto this approccio di Google e volevo condividere questo sentimento con gli altri;)

L'altra cosa è che meglio si ottiene più si tenta di capire e infine non si crede che qualcosa sia buono o cattivo solo perché qualcuno lo ha detto :) Questo è un video molto stimolante che mi ha aiutato a pensare di più da solo :) BUONE PRATICHE sono buone, ma non usarle irrimediabilmente :)




Se si desidera che l'utente inserisca alcune funzioni logiche e valuti per AND the OR, la funzione eval JavaScript è perfetta. Posso accettare due stringhe e eval(uate) string1 === string2 , ecc.




Se noti l'uso di eval () nel tuo codice, ricorda il mantra "eval () è malvagio".

Questa funzione prende una stringa arbitraria e la esegue come codice JavaScript. Quando il codice in questione è noto in anticipo (non determinato in fase di esecuzione), non c'è motivo di utilizzare eval (). Se il codice viene generato dinamicamente in fase di esecuzione, c'è spesso un modo migliore per raggiungere l'obiettivo senza eval (). Ad esempio, solo l'uso della notazione con parentesi quadra per accedere alle proprietà dinamiche è migliore e più semplice:

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

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

L'uso di eval() ha anche implicazioni sulla sicurezza, perché potresti eseguire codice (ad esempio proveniente dalla rete) che è stato manomesso. Questo è un antipattern comune quando si ha a che fare con una risposta JSON da una richiesta Ajax. In questi casi è preferibile utilizzare i metodi incorporati dei browser per analizzare la risposta JSON per assicurarsi che sia sicura e valida. Per i browser che non supportano JSON.parse() modo nativo, puoi utilizzare una libreria da JSON.org.

È anche importante ricordare che passare le stringhe a setInterval() , setTimeout() e al costruttore Function() è, per la maggior parte, simile all'utilizzo di eval() e quindi dovrebbe essere evitato.

Dietro le quinte, JavaScript deve ancora valutare ed eseguire la stringa passata come codice di programmazione:

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

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

L'utilizzo del nuovo costruttore di Function () è simile a eval () e dovrebbe essere affrontato con attenzione. Potrebbe essere un potente costrutto, ma viene spesso utilizzato in modo improprio. Se si deve assolutamente usare eval() , si può prendere in considerazione l'uso della nuova funzione ().

C'è un piccolo vantaggio potenziale perché il codice valutato nella nuova funzione Function () verrà eseguito in un ambito di funzione locale, quindi qualsiasi variabile definita con var nel codice valutato non diventerà globals automaticamente.

Un altro modo per evitare globali automatici è quello di racchiudere la chiamata eval() in una funzione immediata.




Questo potrebbe diventare più un problema in quanto la prossima generazione di browser uscirà con un po 'di sapore da un compilatore JavaScript. Il codice eseguito tramite Eval potrebbe non funzionare come il resto del tuo JavaScript rispetto a questi nuovi browser. Qualcuno dovrebbe fare un po 'di profilazione.




eval () è molto potente e può essere utilizzato per eseguire un'istruzione JS o valutare un'espressione. Ma la domanda non riguarda gli usi di eval (), ma lascia solo dire come la stringa che stai usando con eval () sia influenzata da una parte malintenzionata. Alla fine eseguirai un codice malevolo. Con il potere derivano grandi responsabilità. Quindi usalo saggiamente se lo stai usando. Questo non è molto correlato alla funzione eval () ma questo articolo ha una buona informazione: http://blogs.popart.com/2009/07/javascript-injection-attacks/ Se stai cercando le basi di eval () guarda qui: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval




Non è sempre una cattiva idea. Prendiamo ad esempio la generazione del codice. Recentemente ho scritto una libreria chiamata Hyperbars che colma il divario tra virtual-dom e handlebars . Lo fa analizzando un modello di manubri e convertendolo in un hyperscript che viene successivamente utilizzato da virtual-dom. L'iperscript viene generato come stringa e prima di restituirlo, eval() per trasformarlo in codice eseguibile. Ho trovato eval() in questa particolare situazione l'esatto contrario del male.

Fondamentalmente da

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

A questo

(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({}))

Le prestazioni di eval() non sono un problema in una situazione come questa, perché devi solo interpretare la stringa generata una volta e poi riutilizzare l'output eseguibile più volte.

Puoi vedere come è stata raggiunta la generazione del codice se sei curioso here .




Non tenterò di confutare qualunque cosa sia stata detta finora, ma offrirò questo uso di eval () che (per quanto ne so) non può essere fatto in altro modo. Ci sono probabilmente altri modi per codificarlo, e probabilmente modi per ottimizzarlo, ma questo è fatto a mano e senza campane e fischietti per chiarezza per illustrare un uso di eval che in realtà non ha altre alternative. Ovvero: nomi di oggetti dinamici (o più precisi) creati a livello di programmazione (in contrapposizione ai valori).

//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);

EDIT: a proposito, non suggerirei (per tutti i motivi di sicurezza indicati in precedenza) di basare i nomi degli oggetti sull'input dell'utente. Non riesco a immaginare nessuna buona ragione per cui tu voglia farlo. Eppure, pensavo che avrei fatto notare che non sarebbe stata una buona idea :)




Related

javascript security eval