【问题标题】:Javascript: way to implement 100% tamperproof private variables?Javascript:实现 100% 防篡改私有变量的方法?
【发布时间】:2011-11-30 17:46:52
【问题描述】:

我正在阅读 Crockford 的教程 http://javascript.crockford.com/private.html。 私有变量由构造函数内部的函数实现,这使得私有变量与闭包相关联成为可能。

通常javascript库是开放的,所以任何人都可以通过实例/对象修改构造函数的内部函数来查看和修改私有变量。像这样: c1.radius = function (){return 500;};

更准确地说:在真正的 OOPS 中,没有人可以通过对象修改私有变量,但我们可以。

谁能给我建议如何让它像 JAVA 或 C 一样完全防篡改?

function Circle(radius) {

this.radius = function(){ return radius;}

}

Circle.prototype = {
   constructor: Circle,
   area: function(){
       return (Math.PI)* (Math.pow(this.radius(),2));
   }
};

c1 = new Circle(5);
console.log(c1.radius());
console.log(c1.area());
c1.radius = function (){return 500;};

【问题讨论】:

  • 任何人都可以修改他们有权访问的任何对象。
  • 任何需要 私有的东西都应该存储在服务器上(即使这样你也可以拦截 AJAX 调用)。
  • 我不偏向java或者c,只是问问
  • 像 JAVA 这样的防篡改...:见stackoverflow.com/questions/1555658/… 没有什么是防篡改。如果由于有人找到了规避设计的方法而出现问题(我们讨论的是封装,而不是安全,如数据安全这里),那么这是他们的错误,而不是设计的错误。 (顺便说一句,C 中可以有 私有变量 吗?)
  • 你参考的文章中Crockford关于如何制作私有变量的描述有什么问题?他们是私人的。只有您在构造函数中定义的方法才能修改它们。外部代码无法修改它们。即使您自己在别处定义的代码也无法修改它们。

标签: javascript


【解决方案1】:

第一关,不要太担心防篡改。如果有人真的想要,他们将能够访问他们想要的东西。

第二,除非您使用 ECMAScript 5(IE9+、Safari 5+、Chrome 7+、FF 4+),否则您无法真正做到这一点。如果您使用的是 ES5 浏览器,您可以使用 Object.defineProperty 方法或使用 Object.create 来做您想做的事情:

function Circle(radius) {
    Object.defineProperty(this, 'radius', {
        value: radius
    });
}

注意:使用Object.createObject.defineProperty 时,属性默认为不可写、不可配置(类型无法更改且属性无法删除)和不可枚举(不会出现在for(var x in obj) 构造中)。

【讨论】:

    【解决方案2】:

    这个怎么样?

    function oTest(){
      var a; // "private"
      this.b; // "public"
    
      this.get_a = function(){
        return a
      )
    }
    
    var aTest = new oTest();
    aTest.private_get = function(){
      return a
    } 
    
    aTest.private_get() // ReferenceError: a is not defined
    aTest.get_a() // works
    

    我不确定我是否完全理解您的问题,但 a 仅适用于提供的原始方法集。

    【讨论】:

      【解决方案3】:

      您可能想查看traits.js。在以下示例中,半径和面积是不可变的或防篡改的。

      function TCircle(radius) {
          return Trait.create(
              Object.prototype,
              Trait({
                  radius: radius,
                  area: function() {
                      return (Math.PI) * (Math.pow(this.radius, 2));
                  }
              }));
      }
      
      var circle = TCircle(5);
      console.log(circle.area()); // 78.53981633974483
      circle.radius = null;
      console.log(circle.area()); // 78.53981633974483
      circle.radius = 99;
      console.log(circle.area()); // 78.53981633974483
      

      如果你想要一个可变对象,那么你应该使用Object.create 而不是上面的Trait.create

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-04-30
        • 1970-01-01
        • 2015-06-30
        • 1970-01-01
        • 2011-10-06
        • 2012-03-27
        • 2016-05-19
        相关资源
        最近更新 更多