问题
Mozilla's Content Security Policy disallows the use of javascript eval function as well as inline scripts. They claim that all instances of eval can be replaced by another (hopefully safer) function. I agree in most scenarios, Javascript eval can be replaced, but I'm not sure whether the replacement is possible for every case.
My question is twofold:
- Is there a generic way to replace every javascript eval function? (doesn't have to be safe)
- Is there a case where the Javascript eval cannot be replaced?
回答1:
The most common uses which can be substituted are the following ones. I would certainly use these first.
Accessing dynamic properties
Do use:
obj[keyAsVariable]
Don't use
eval('obj.' + keyAsVariable)
Parsing JSON
Do use
JSON.parse(data)
Don't use
eval('(' + data + ')')
Calculating user input
Do use a certain library
Don't use
eval(input)
If really necessary, you can also send the script to a server which simply echoes it back, and you can request it as a script tag. It won't use eval
but still execute it. It isn't safe as it's sent twice over the Internet.
var s = document.createElement('script')
s.src = 'request_script?data=' + data;
document.getElementsByTagName('head')[0].appendChild(s);
request_script
could be a file implemented in PHP, like the following. Again, it's bad practice but is a generic way of circumventing eval
.
<?
echo $_GET['data'];
?>
You could say that this also automatically answers your second question with 'no'.
回答2:
You could wrap the java script within a function call similar to JSONP and then dynamically create a script tag to load that.
回答3:
Load as script using a Blob
Instead of using eval
you can also use a Blob
and load the code as if it was an external js
file:
To ensure that functions or variables that are inside the code that you are loading are available you need to use a callback
method that will be triggered onload
event.
var code = "console.log('hello world');";
// With eval:
eval(code);
// With a blob:
var blob = new Blob([code], {type: 'text/javascript'});
var urlCreator = window.URL || window.webkitURL;
var url = urlCreator.createObjectURL( blob );
function loadScript(url, callback)
{
// Add a the script tag to the head
var head = document.getElementsByTagName('head')[0];
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = url;
// Bind the callback (depends on browser compatibility).
script.onreadystatechange = callback;
script.onload = callback;
// Load the script
head.appendChild(script);
}
// Any variables or methods inside the code will be on callback.
loadScript(url, callback);
Note Be aware that the danger for code injection is similar to eval.
来源:https://stackoverflow.com/questions/7127652/alternatives-for-javascript-eval