Проверьте, было ли глобальное свойство / функция перезаписано в 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>
Другие вопросы по тегам