【问题标题】:Is a private member secure in javascript?javascript 中的私有成员是否安全?
【发布时间】:2020-09-18 12:25:05
【问题描述】:

我正在关注freecodecamp JavaScript oop 课程。本课程介绍了如何在对象内部声明一个私有变量,以应对无法从外部更改的密码和银行账户等情况。对私有变量的唯一访问是通过可以访问私有变量的公共方法。然后给出这个演示代码来说明这一点。

function Bird() {
  let hatchedEgg = 10; // private variable

  /* publicly available method that a bird object can use */
  this.getHatchedEggCount = function() { 
    return hatchedEgg;
  };
}
let ducky = new Bird();
ducky.getHatchedEggCount(); // returns 10

我不明白的是,hatchedEgg 变量如何被称为安全变量。 作为用户/黑客,我所要做的就是猜测从函数 getHatchedEggCount() 返回的变量名称。在这种情况下,hatchedEgg(这对黑客来说并不太难),然后我可以使用这一行来修改私有变量;

Bird.hatchedEgg = 20;
console.log(Bird) // returns { [Function: Bird] hatchedEgg : 20 }

我错过了什么吗?

//-------------- Clarification Edit

显然问题出在 freecodecamp 控制台 (A Bug) 上,它正在更改私有变量的值。 如果你愿意,你可以尝试在这个链接中粘贴上面的代码,你会看到。 freecodeConsoleLink

【问题讨论】:

  • 为什么不自己尝试一下呢?您不必是黑客,您已经知道变量的名称。只需尝试控制台登录 ducky.hatchedEgg 看看你得到了什么。剧透:你不会得到 private 变量的值。
  • 不。零“安全”。在客户端上用 JavaScript 执行的任何东西都可能是不安全的;缓解措施是最小化潜在风险(例如 XSS),正确确保服务器上的操作安全(例如 HTTPs 和反 CSFR),并定义“可信”数据/访问。最低限度,如果可以注入任意 JS,那么整个对象可能会被重新定义。
  • 顺便说一句,什么是 JavaScript oops 课程
  • @Sнаđошƒаӽ 哈哈我的意思是哎呀看到这个链接freecodecamp.org/learn/…
  • 还有你展示的黑客可能会做的例子,它不会改变在内部函数Bird中定义的变量hatchedEgg,它只会在Bird中创建一个字段对象。毕竟,函数是 JavaScript 中的第一类对象。

标签: javascript oop private


【解决方案1】:

直接调用ducky.hatchedEgg(我猜你的意思是这个而不是Bird.hatchedEgg)不会给你任何结果(准确地说是undefined)。这就是示例的重点,即不能从外部直接访问私有变量。它们是通过一种方法访问的,而该方法又可能/不能暴露于外部。安全性由此而来。

更新我再次阅读了这个问题,您正在做的是:您将属性hatchedEgg 附加到Bird 并为其设置一个值。

Bird.hatchedEgg = 20

但是,这个 hatchedEgg 与函数中最初定义的 let hatchedEgg = 10; 不同。

ducky.getHatchedEggCount(); 仍然会给你 10。Bird.hatchedEgg 会给你20,因为你将属性hatchedEgg 附加到对象Bird 这与在函数@ 中声明的hatchedEgg 不同987654335@.

此外,functions 是一流的对象,您可以像处理任何其他对象一样向其添加/删除属性。但是,在上一篇文章中,我故意尝试区分functionBird 和objectBird,以使事情清楚。这就像说,arrays 也是objects。但是你在谈话中保持一种区分,以便把事情简单化。无论如何,我认为更新它会导致某种混乱。

【讨论】:

  • 我不是说ducky.hatchedEgg 我是说Bird.hatchedEgg。 Bird.hatchedEgg 确实记录未定义但看到我所做的编辑,我仍然可以为 hathedEgg 赋予新价值
  • 更正:Bird.hatchedEgg 也将是 undefinedBird().hatchedEgg 会给你一个错误。
  • Rahul,你说“bird 是一个函数,而不是一个对象”,但Bird.hatchedEgg 是一个对象也是一个函数。函数是对象。因此,如果您为其分配属性Bird.hatchedEgg = 5,您可以像使用普通对象Bird.hatchedEgg 一样访问这些属性。
  • Functions 是一流的对象 - 是的。我故意不想进入那个,因为我想保持functionobject 之间的区别。就像arrays 也是对象一样,但对于简单的对话,我们保持区别。但无论如何,当您附加一个属性时,您并没有对函数中最初定义的 let hatchedEgg 变量做任何事情。无论如何,立即查看更新的答案
【解决方案2】:

正如 freecodecamp 主题中所述,它被称为闭包。只需使用非常琐碎的编程概念就可以这样想:

在函数内部声明的变量的作用域仅限于该函数,无法从函数外部访问这些变量。这不仅适用于 JavaScript,适用于所有其他语言。

现在,为什么我们可以从外部获取该作用域变量的值是闭包的魔法。由于题中并没有提到“闭包”这个词,更不用说去问了,所以这里就不细说闭包了。

至于你所说的黑客可以用来破解它的代码,那一行

Bird.hatchedEgg = 20;

只在 object Bird 内创建一个属性。这里的另一个基本概念 - 函数Bird 也是 JavaScript 中的第一类对象,这意味着它可以像任何其他对象一样具有属性和函数。 Bird.hatchedEgg指的是Bird对象的属性,而Bird函数内部声明的变量(带let hatchedEgg = 10;)是函数的局部变量,两者是不同的。如果该行要更改函数内声明的局部变量的值,则在控制台日志ducky.getHatchedEggCount() 时应该会得到相同的结果,但不会。

【讨论】:

    【解决方案3】:

    我认为您对正在创建的变量以及如何访问每个变量感到有些困惑。

    你从一个函数开始:

    function Bird() {
      let hatchedEgg = 10;
    
      this.getHatchedEggCount = function () {
        return hatchedEgg;
      };
    }
    

    这个函数没有任何属性。

    调用此函数时,它只是将getHatchedEggCount 属性附加到this 对象。 getHatchedEggCount 属性本身就是一个函数,它引用了在 Bird 函数运行时创建的 hatchedEgg 变量。

    因此我们可以这样做:

    // We call the 'Bird' function.
    // As we are using the 'new' keyword, we create an empty context for the function.
    // The empty context is referenced using the 'this' keyword inside the 'Bird' function.
    // We assign 'getHatchedEggCount' as a method on the 'this' empty object
    // We then return the 'this' object
    // The 'ducky' variable now points to the returned 'this' object
    // Therefore the 'ducky' variable is an object with a 'getHatchedEggCount' method
    let ducky = new Bird();
    

    控制台日志会给出以下输出:

    console.log(ducky);
    // Output: Bird { getHatchedEggCount: [Function] }
    
    console.log(ducky.hatchedEgg);
    // Output: undefined
    
    console.log(ducky.getHatchedEggCount());
    // Output: 10
    

    这一切都在意料之中,因为ducky 是一个只有一个属性的对象——getHatchedEggCount 方法。

    但最重要的是,请注意当我们记录以下内容时会发生什么:

    console.log(Bird);
    // Output: [Function: Bird]
    
    console.log(Bird.hatchedEgg);
    // Output: undefined
    
    console.log(Bird.getHatchedEggCount);
    // Output: undefined
    

    我们看到Bird 函数实际上是一个空对象。它没有属性(我们自己分配的),因此Bird.hatchedEgg 不存在!

    那么为什么我们在调用ducky.getHatchedEggCount() 时可以访问hatchedEgg 变量呢?这是由于闭包是如何工作的,但这是题外话。不用说,hatchedEgg 变量只能由 getHatchedEggCount 函数访问。

    现在,如果我们说:

        Bird.hatchedEgg = 20;
    

    我们正在向Bird 函数添加一个全新的属性。所以我们可以控制台日志:

    console.log(Bird);
    // Output: [Function: Bird] { hatchedEgg: 20 }
    
    console.log(Bird.hatchedEgg);
    // Output: 20
    

    我们在Bird 函数中添加了一个新的hatchedEgg 属性,这是以前不存在的!

    但是请注意,这与getHatchedEggCount 函数使用的hatchedEgg 变量的属性不同。

    原始的hatchedEgg 变量是在Bird 函数内创建的,可以在函数体内访问,但不是Bird 函数对象的属性,因此无法通过以下方式访问Bird.hatchedEgg。你看出区别了吗?

    例如,运行以下代码:

    function Bird() {
      let hatchedEgg = 10;
    
      this.getHatchedEggCount = function () {
        return hatchedEgg;
      };
    }
    
    Bird.hatchedEgg = 20;
    console.log(Bird.hatchedEgg);
    // Output: 20
    
    let ducky = new Bird();
    console.log(ducky.getHatchedEggCount());
    // Output: 10
    

    您知道为什么具有10 值的hatchedEgg 变量仍然无法访问吗?它与Ducky.hatchedEgg 不是同一个变量。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-03-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-26
      • 1970-01-01
      • 1970-01-01
      • 2015-11-02
      • 2012-03-10
      相关资源
      最近更新 更多