16

考虑这个伪代码:

(function(window){
   var options = { /*where everything goes */ };

   var instance = (function(options){
       for (var i in options){
       if (options.hasOwnProperty(i)){
         this[i] = options[i];
       }
     }
   })(options);

   instance.callbacks = function(cb){
     //...
   }

   instance.is_allowed = function()
    //... checks, return boolean
   }

   window.instance = instance;
})(this);

如果有人想要操纵这段代码(例如恶意用户),他会is_allowed用自己的函数重写该函数,例如使用地址栏(他没有 firebug,谁知道)。

javascript:(function(){ window.instance.is_allowed = function(){ return true; } })();

这是一个幼稚的例子,但这就是重点,Javascript 中的任何内容都可以被覆盖。

我知道在 es5 我们有 Object.defineProperty 所以你可以设置:

// being explicit
Object.defineProperty(instance, "is_allowed", {
  enumerable: false,
  configurable: false,
  writable: false,
  value: function(){
    // do checks
  }    
});

实际上,从这个意义上说,最好的方法是使用Object.freeze(instance)orObject.seal(instance)代替Object.defineProperty,因为后者可以再次调用writable: false(傻吧?)

有没有什么方法可以在旧浏览器(即 IE6-8)中运行而没有太多麻烦?如果不可能,那我就耸耸肩继续前进。

4

3 回答 3

2

提议

我不会说我是这些事情的专家。但是假设您可以完全包装您的代码并使用事件来触发行为,您可以使用如下结构:

Closed = function(args) { return (function() {
  "use strict";

  var secret, init, get_secret, use_secret;

  init = function(something){
    secret = something;
  };

  get_secret = function() {
    return secret;
  };

  use_secret = function () {
    console.log(secret);
  };

  /* Run constructor */
  init(args);

  /* Publish API */
  return { use_secret:use_secret };

}())};

obj = Closed("Anything");与您一起设置它仍然可以让恶意用户覆盖该use_secret()方法,因为它已暴露,但该get_secret()方法和任何其他内部结构都受到保护。

如果您的 init 方法声明了许多与应用程序的事件绑定,您可以通过这种方式将您的状态保持为私有。这些事件将能够触发内部方法,因为它们是从内部闭包内部绑定的,但外部代码不会看到它们。

预订

虽然这可能会解决您的问题,但我不能 100% 肯定它确实如此,无论如何也不值得信任。只要安全性在客户端,任何想要渗透您的应用程序的用户都可以。无论如何,没有什么可以阻止他们制作自己的对象来替换您的对象,无论是 ES5 还是没有 ES5。

对于任何真正需要安全的东西,您都必须在服务器端重新验证。永远不要相信客户端代码来保护你,请求甚至可能不是来自你服务的页面......

于 2013-02-03T15:21:22.340 回答
2

如果有人想要操纵这段代码(例如恶意用户),他会用自己的代码重写 is_allowed 函数

他可以重写您的整个 javascript 代码,甚至不使用浏览器,而是模拟对您的服务器的“无浏览器”请求。

有没有什么方法可以在旧浏览器(即 IE6-8)中运行而没有太多麻烦?

不可以。用户可以更改您全局公开的任何内容,这取决于浏览器限制javascript:行为以避免用户被愚弄访问预先制作的链接。Firefox 最近对 javascript URL 协议进行了某种更改。

如本文所述:http ://survey-remover.com/blog/javascript-protocol-dangers/

从 Chrome v13、Firefox v6 和 IE 9 开始,浏览器开发人员已经注意到“javascript:”协议的危险性并随后禁止使用代码……对于 Chrome 和 IE,“javascript:”子字符串是粘贴代码时被剥离,而 Firefox 不再在活动页面范围内执行脚本。

所以...

如果不可能,那我就耸耸肩继续前进。

你应该。

于 2013-02-05T21:54:32.027 回答
0

如果is_allowed完全是本地的呢?

(function(window){
   var options = {}, is_allowed;

   var instance = (function(options){
     for (var i in options) {
     if (options.hasOwnProperty(i)) {
        this[i] = options[i];
       }
     }
     return this;
   })(options);

   instance.callbacks = function(cb){
       /* ... */
   };

   function check_allowed(){
     /* check and let this function set [is_allowed] */
   };

  window.instance = check_allowed()
                     ? instance
                     : { callbacks: function(){(alert('not allowed'));}  };

} (this) );

jsBin样机

顺便说一句:在您的代码中,window.instance将是undefined.

于 2013-02-03T11:08:27.673 回答