javascript 有没有办法防止在单例实例中覆盖/覆盖函数/变量?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14671332/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 22:17:34  来源:igfitidea点击:

Is there any way to prevent override/overwrite of functions/variables in singleton instance?

javascriptsingletonjavascript-objectsoverwrite

提问by pocesar

Consider this pseudo code:

考虑这个伪代码:

(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);

If anyone ever wanted to manipulate this code (a malicious user for example), he would rewrite the is_allowedfunction with his own, for example, using the address bar (he doesn't have firebug, who knows).

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

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

This is a naive example, but that's the point, anything in Javascript can be overwritten.

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

I know in es5 we have the Object.defineProperty so you can set:

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

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

Actually, what is BEST in this sense is to use Object.freeze(instance)or Object.seal(instance)instead of Object.defineProperty, since the later can be called again with writable: false(silly huh?)

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

Is there ANY way that it work in old browsers (namely IE6-8) without too much hassle? If it's impossible, then I'll just shrug and move on.

有没有什么办法让它在旧浏览器(即 IE6-8)中工作而不会太麻烦?如果这是不可能的,那我就耸耸肩继续前进。

采纳答案by Fagner Brack

If anyone ever wanted to manipulate this code (a malicious user for example), he would rewrite the is_allowed function with his own

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

He could rewrite your whole javascript code or not even use a browser but simulate a "browser-less" request to your server.

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

Is there ANY way that it work in old browsers (namely IE6-8) without too much hassle?

有没有什么办法让它在旧浏览器(即 IE6-8)中工作而不会太麻烦?

No. Anything you globally expose can be altered by the user, it is up to the browsers restrict the javascript:behavior to avoid users from being fooled to access pre-crafted links. Firefox recently have made some kind of change to the javascript URL protocol.

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

As said on this article: http://survey-remover.com/blog/javascript-protocol-dangers/

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

As of Chrome v13, Firefox v6 and IE 9, the browser developers have taken notice to the dangers of the "javascript:" protocol and have subsequently disallowed code ... In the case of Chrome and IE, the "javascript:" substring is stripped when the code is pasted, whereas Firefox no longer executes the script within the scope of the active page.

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

So...

所以...

If it's impossible, then I'll just shrug and move on.

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

You should.

你应该。

回答by Jonas Schubert Erlandsson

Proposal

提议

I won't say I'm an expert on these things. But assuming you can wrap your code completely and use events to trigger behavior you can use a structure like this:

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

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 };

}())};

Setting it up with obj = Closed("Anything");you can still have a malicious user overwrite the use_secret()method, since it's exposed, but the get_secret()method, and any other internals, are protected.

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

If your init method declares a number of event bindings to the application you can keep your state private in this way. The events will be able to trigger internal methods since they where bound from inside the inner closure but external code won't see them.

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

Reservations

预订

While this might solve your problem, I'm not 100% sure it does, it's not to be trusted anyway. Any user that want to penetrate your application can as long as the security is on the client side. There is nothing to stop them from crafting their own object to replace yours after the fact anyway, ES5 or no ES5.

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

For anything that actually needs to be secure you will have to revalidate on the server side. Never trust client side code to protect you, the request might not even come from the page you served ...

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

回答by KooiInc

What if is_allowedwould be completely local?

如果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) );

jsBinmockup

jsBin样机

BTW: in your code, window.instancewould be undefined.

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