säkerhet - Varför är det en dålig idé att använda JavaScript-funktionen eval?


Eval-funktionen är ett kraftfullt och enkelt sätt att dynamiskt generera kod, så vilka är varningarna?

Svar #1

  1. Felaktig användning av eval öppnar upp din kod för injektionsattacker

  2. Felsökning kan vara mer utmanande (inga radnummer, etc.)

  3. eval'd kod körs långsammare (ingen möjlighet att kompilera/cacha eval'd kod)

Redigera: Som @Jeff Walden påpekar i kommentarerna, är #3 mindre sant idag än det var 2008. Dock, medan viss cachning av kompilerade skript kan ske, kommer detta endast att begränsas till skript som eval'as upprepade gånger utan ändringar. Ett mer troligt scenario är att du eval'ar skript som har genomgått små ändringar varje gång och därför inte kan cachas. Låt oss bara säga att VISSA eval'ade koder körs långsammare.

Svar #2

eval är inte alltid ond. Det finns tillfällen då det är helt lämpligt.

Dock används eval för närvarande och historiskt sett massivt av människor som inte vet vad de håller på med. Det inkluderar tyvärr även människor som skriver JavaScript-handledningar, och i vissa fall kan detta faktiskt ha säkerhetskonsekvenser - eller, oftare, enkla buggar. Så ju mer vi kan göra för att ifrågasätta eval, desto bättre. Varje gång du använder eval behöver du kontrollera vad du gör, eftersom chansen är stor att du skulle kunna göra det på ett bättre, säkrare och renare sätt.

För att ge ett alltför typiskt exempel, för att ange färgen på ett element med ett id lagrat i variabeln 'potato':

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

Om författarna till den typ av kod ovan hade haft en aning om grunderna i hur JavaScript-objekt fungerar, skulle de ha insett att hakparenteser kan användas istället för bokstavliga punkt-namn, vilket gör användningen av eval överflödig:

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

...vilket också är mycket lättare att läsa samt mindre potentiellt buggtätt.

(Men då skulle någon som verkligen visste vad de gjorde säga:

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

vilket är mer tillförlitligt än det skumma gamla tricket att få åtkomst till DOM-element direkt från dokumentobjektet.)

Svar #3

Jag tror att det beror på att det kan köra vilken JavaScript-funktion som helst från en sträng. Att använda det gör det lättare för människor att injicera skadlig kod i applikationen.

Svar #4

Det är i allmänhet bara ett problem om du skickar användarinmatning till eval.

Svar #5

Två punkter kommer i åtanke:

  1. Säkerhet (men så länge du själv genererar strängen som ska utvärderas, kan detta vara ett icke-problem)

  2. Prestanda: tills koden som ska köras är okänd, kan den inte optimeras. (om JavaScript och prestanda, säkert Steve Yegges presentation)

Svar #6

Att skicka användarinmatning till eval() är en säkerhetsrisk, men varje anrop av eval() skapar också en ny instans av JavaScript-tolken. Detta kan vara resurskrävande.

Svar #7

Främst är det mycket svårare att underhålla och felsöka. Det är som en goto. Du kan använda det, men det gör det svårare att hitta problem och svårare för de som senare kan behöva göra ändringar.

Svar #8

Om du inte låter eval() hantera dynamiskt innehåll (genom cgi eller inmatning), är det lika säkert och stabilt som all annan JavaScript på din sida.

Svar #9

En sak att komma ihåg är att du ofta kan använda eval() för att köra kod i en annars begränsad miljö - sociala nätverkssajter som blockerar specifika JavaScript-funktioner kan ibland luras genom att bryta upp dem i ett eval-block -

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

Så om du vill köra lite JavaScript-kod där det annars kanske inte skulle tillåtas (Myspace, jag tittar på dig...) kan eval() vara ett användbart trick.

Men av alla ovan nämnda skäl bör du inte använda det för din egen kod, där du har fullständig kontroll - det är helt enkelt inte nödvändigt, och bättre att hänskjuta till hyllan för 'knepiga JavaScript-hacks'.

Relaterade artiklar