5

JavaScript 使覆盖全局对象的属性和函数变得容易。我想找到一种方法来检查全局属性的原始版本是否已被替换。

考虑有人把它放在他们的 HTML 中:

<script type="text/javascript">
    window.encodeURIComponent = eval;
</script>
<script type="text/javascript" src="myscript.js"></script>

如果 myscript.js 在某处调用 encodeURIComponent 函数,它现在的行为将无法预测。那么有没有一种方法可以在 myscript.js 内部检查是否有人在我使用之前覆盖了该函数?

4

5 回答 5

8

我唯一知道的是一种简单的方法,可以分析函数的字符串表示。通常,代码

window.encodeURIComponent.toString()

应该产生这样的东西:

function encodeURIComponent() { [native code] }

可以轻松解析关键信息function encodeURIComponent

如果函数被 覆盖eval,如您的示例所示,您将获得:

function eval() { [native code] }

一般来说,为了检查window属性,您可以创建一个假 iframe 并window.[property].toString()iframe.contentWindow.[property].toString(). 如果比较给出false,则属性已更改。

于 2012-04-22T08:39:16.843 回答
3

在一个脚本中执行此操作的一种有趣方法是比较函数原型

默认 -typeof window.encodeURIComponent.prototype === "undefined"

但是如果有人重新定义这个函数

window.encodeURIComponent = function() { eval(); } 我们将得到

typeof window.encodeURIComponent.prototype === "Object"

PS:这种方法比其他方法更可靠,但它不会给你100%的保证。JavaScript 是所有对象,并且都在运行时.. 只是忍受这个..

更新 你可以结合这两种方法..我的和@Stans..

这个例子不起作用,因为我没有使用eval- eval 默认情况下也有原型“未定义”..所以你可以这样做

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
于 2012-04-22T09:29:08.267 回答
1

这是特定于浏览器的,绝对不适用于非功能,但是:

调用函数的toString方法应该产生类似的结果:

Chrome:

"function encodeURIComponent() { [native code] }"

Firefox:

"function encodeURIComponent() {
    [native code]
}"

IE 7/8/9:
"
function encodeURIComponent() {
    [native code]
}
" 

观察函数的名称与属性的名称匹配,并且它的主体被替换为“ [native code]”。想法是从该字符串中删除所有空格并将其与预期结果进行比较"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!");
}
于 2012-04-22T08:34:32.520 回答
1

这个怎么样?

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
于 2015-05-05T13:57:39.047 回答
0

在 JavaScript 中有一种简单的方法 :) 但是您必须有权访问 HTML,因此您不能在一个脚本中使用此方法..

function 是一个 OBJECT.. 所以我们可以保存一个对象的链接并比较这些链接。把一个函数想象成一个简单的对象。你怎么能比较对象?

<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>
于 2012-04-22T08:44:23.767 回答