Проверьте, было ли глобальное свойство / функция перезаписано в JavaScript
JavaScript позволяет легко перезаписывать свойства и функции глобального объекта. Я хотел бы найти способ проверить, была ли заменена исходная версия глобального свойства.
Подумайте, кто-то вставил это в свой HTML
<script type="text/javascript">
window.encodeURIComponent = eval;
</script>
<script type="text/javascript" src="myscript.js"></script>
Если myscript.js вызывает функцию encodeURIComponent где-то, он теперь будет вести себя непредсказуемо. Так есть ли способ проверить внутри myscript.js, переписал ли кто-нибудь эту функцию, прежде чем я ее использую?
5 ответов
Единственное, что я знаю, - это простой подход с анализом строкового представления функции. Обычно код
window.encodeURIComponent.toString()
должен произвести что-то вроде этого:
function encodeURIComponent() { [native code] }
которые могут быть легко проанализированы для ключевой информации function encodeURIComponent
,
Если функция была перезаписана eval
, как в вашем примере, вы получите:
function eval() { [native code] }
В общем, для проверки window
свойства, вы можете создать поддельный iframe и сравнить window.[property].toString()
с iframe.contentWindow.[property].toString()
, Если сравнение дает false
, собственность была изменена.
Один интересный способ сделать это внутри одного скрипта - сравнить прототип функции
По умолчанию - typeof window.encodeURIComponent.prototype === "undefined"
Но если кто-то переопределяет эту функцию
window.encodeURIComponent = function() { eval(); }
мы получим
typeof window.encodeURIComponent.prototype === "Object"
PS: этот метод более надежен, чем другие, но он не даст вам 100% гарантии. JavaScript это все объекты и все во время выполнения.. просто жить с этим..
ОБНОВЛЕНИЕ вы можете объединить оба метода.. мой и @Stans..
этот пример не работает, потому что я не использовал eval
- eval также имеет прототип "undefined" по умолчанию.. так что вы можете сделать это
window.encodeURIComponent.name === "encodeURIComponent"
//to make shure that user won't use EVAL
&& typeof window.encodeURIComponent.prototype === "undefined"
//to make shure that user won't use self defined function
Как насчет этого?
function isNativeWindowProperty(propertyName) {
var result = false;
var iframe = document.createElement('iframe');
iframe.src = 'javascript:;';
document.getElementsByTagName('body')[0].appendChild(iframe);
if (window[propertyName].toString() === iframe.contentWindow[propertyName].toString()) {
// check window[propertyName].toString override
if (window[propertyName].toString.toString() === iframe.contentWindow[propertyName].toString.toString()) {
result = true;
}
}
iframe.parentNode.removeChild(iframe);
return result;
};
console.log(isNativeWindowProperty('alert')); // true
window.alert = function() {};
console.log(isNativeWindowProperty('alert')); // false
window.alert.toString = function() {
return 'function alert() { [native code] }';
};
console.log(isNativeWindowProperty('alert')); // false
Это зависит от браузера и определенно не будет работать для не-функций, но:
Вызов функции toString
Метод должен производить что-то вроде:
Chrome:
"function encodeURIComponent() { [native code] }"
Firefox:
"function encodeURIComponent() {
[native code]
}"
IE 7/8/9:
"
function encodeURIComponent() {
[native code]
}
"
Обратите внимание, что имя функции совпадает с именем свойства, а ее тело заменяется на "[native code]
Msgstr "Идея состоит в том, чтобы удалить все пробелы из этой строки и сравнить ее с ожидаемым результатом, "functionxxx(){[nativecode]}"
,
Я понятия не имею, работает ли он для всех браузеров / функций, это метод проб и ошибок:
var pattern = 'function' + propertyName + '(){[nativecode]}';
var func = window[propertyName].toString();
if(func.replace(/\s+/g, '') !== pattern) {
throw new Error("Property window." + propertyName + " has been modified!");
}
Есть простой способ сделать это в JavaScript:) Но вы должны иметь доступ к HTML, поэтому вы не можете использовать этот метод внутри одного скрипта..
функция - это ОБЪЕКТ. поэтому мы можем сохранить ссылку на объект и просто сравнить эти ссылки. Просто подумайте о функции, как это простой объект. Как вы можете сравнить объекты?
<script type="text/javascript">
var a = window.encodeURIComponent; // a === window.encodeURIComponent -> true
</script>
<script type="text/javascript">
window.encodeURIComponent = eval; // a === window.encodeURIComponent -> false
</script>
<script type="text/javascript" src="myscript.js">
if (a !== window.encodeURIComponent)
{
throw new Error('Someone redefined function');
}
</script>