javascript函数对象的实例是否不可变

javascript函数对象的实例是否不可变,javascript,web-services,security,Javascript,Web Services,Security,我说函数对象的实例是不可变的,因为我们无法在函数创建后修改它,对吗 无论如何,我要重新表述我的问题: var f1=function(){ return true; } //Now i pass **f1** into the function **G**, storing it to **g1** function G(f){ return function(){ return f(); } }

我说函数对象的实例是不可变的,因为我们无法在函数创建后修改它,对吗

无论如何,我要重新表述我的问题:

  var f1=function(){
        return true;
    }

    //Now i pass **f1** into the function **G**, storing it to **g1**
    function G(f){
    return function(){
            return f();
    }
    }
    var g1=G(f1);

    //I will try to hack/do anything i can to **f1**
    //Now i will pass f1 to hacked piece of injection code which (assumingly) will try to hack f1


    g1(); // but I can be 100% sure this will still return me true
因此,现在我可以确定,无论我对f1做了什么,g1()都将永远返回给我真的

尽管我对占互联网用户市场份额至少0.5%的浏览器感兴趣,但我还是欢迎类似于“在[x]浏览器中,这是不安全的,因为……”这样的回答

我知道,由于代码是在客户端运行的,如果客户端有恶意意图,他将能够做任何他想做的事情。。但这个问题专门针对保护“没有恶意意图的用户”,换句话说。。一个普通用户(如果用户是黑客,我不介意让他随意乱动函数,因为他会把所有异常都扔到脸上,这不关我的事)

不:

var f = new Function("");
f.prop = 1;

无法阻止在所有浏览器上重新分配变量
g1
。某些浏览器允许您将
g1
定义为:

这将防止名称
g1
反弹,您可以使用
Object.defineProperty
在其他对象上定义
window
的全局属性,但通常JavaScript中没有
const
定义

为了更清楚,考虑两种情况:

(1) 攻击者可以在声明
f1
的范围内运行代码,然后其他代码读取
f1

var f1 = ...;   // You define f1
f1 = function () { return false; };  // Attacker code runs
doSomethingWith(f1());  // Naive code reads f1 and calls it.
在这种情况下,攻击者成功地混淆了原始代码,因为他们更改了
f1
处的值

var f1 = ...;   // You define f1
f1 = function () { return false; };  // Attacker code runs
doSomethingWith(f1());  // Naive code reads f1 and calls it.
(2) 攻击者在读取
f1
后在作用域中运行代码

var f1 = ...;  // You define f1
// Cautious code reads and stores f1 in a safe place for later use.
(function () {
  var f = f1;
  setTimeout(0, function () { doSomethingWith(f()); });
})();
f1 = function () { return false; };  // Attacker code runs.

在这种情况下,攻击者失败,因为在攻击者更改存储在
f1
的值之前,谨慎的代码读取了
f1
的值,因此,私有
f
继续返回
true

您是指函数体还是对象的属性?@Jeremy Heiler我编辑了这个问题,您的代码在调用
g1()
时会出错,因为
g1
true
。我想你的意思是让
G
be
返回f。无论哪种方式,您所做的只是传递
f1
,因此,在本例中,对它的任何更改都将反映在任何位置。但是,我认为在函数声明之后没有合法的方法来更改函数体。这还取决于函数是否引用了它外部的任何内容。@Jeremy Heiler不,函数不引用外部的任何内容。所以基本上我们可以100%确定功能体不能被触碰?@Pacerier:我知道的唯一方法是用一个新功能完全替换功能体。由于
g1
现在包含了对
f1
中函数的引用,因此替换
f1
的主体并不重要。这就是我现在所能说的,我当然没有资格说我百分之百肯定不会有其他事情发生。我不想承担责任:-代码中的严重错误。。我已经编辑了我的问题:它不是您假设的代码。。但是:
函数G(f){return function(){return f;}}
@Pacerier,删除了关于G的定义,因为它看起来像是你的新定义可以满足你的需要。这篇文章的其余部分,关于如何使名称
g1
始终指向同一个函数实例(模屏蔽)仍然是相关的。因此,即使我将名为
f1
的函数实例传递到攻击者的脚本中,他可以做他想做的任何事,但是在他的脚本结束时,我仍然可以调用
f1
,并说它将100%返回true?@Pacerier,如果你通过
f1()
调用
f1
,它要么接受零个参数,要么不调用任何参数,那么它仍然会给你
true
。显然,如果您定义一个函数调用它的一个参数
var h1=function(f,x){return f(x);}
并将其传递给攻击者,那么攻击者可以通过执行
h1(eval,“h1=function(){…}”)
重命名
h1
。您应该始终怀疑
的值,因为攻击者可以像控制任何其他参数一样轻松地控制它。并且您应该小心在传递给攻击者的任何函数的代码中存储机密;您不希望
f.toString()
返回类似
function(){var privateKey=“…”;…}
的内容。