Czy jest jakiś sposób, aby zapobiec nadpisywaniu / nadpisywaniu funkcji / zmiennych w instancji singleton?

Rozważ ten pseudo kod:

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

Jeśli ktoś kiedykolwiek chciał manipulować tym kodem( na przykład złośliwy użytkownik), przepisałby funkcję is_allowed swoją własną, na przykład używając paska adresu(nie ma firebuga, kto wie).

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

To naiwny przykład, ale o to chodzi, wszystko w Javascript można nadpisać.

Wiem, że w es5 mamy obiekt.defineProperty więc można ustawić:

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

Właściwie to, co jest najlepsze w tym sensie, to aby użyć Object.freeze(instance) lub Object.seal(instance) zamiast Object.defineProperty, ponieważ później można wywołać ponownie za pomocą writable: false (głupie huh?)

Czy jest jakiś sposób, aby to działało w starych przeglądarkach (mianowicie IE6-8) bez zbytniego kłopotu? Jeśli to niemożliwe, wzruszę ramionami i ruszę dalej.

Author: pocesar, 2013-02-03

3 answers

Jeśli ktoś kiedykolwiek chciał manipulować tym kodem (złośliwy użytkownik dla przykład), przepisałby funkcję is_allowed za pomocą własnego

Może przepisać cały kod javascript lub nawet nie używać przeglądarki, ale symulować żądanie "bez przeglądarki" do serwera.

Czy jest jakis sposob aby dzialal w starych przegladarkach (mianowicie IE6-8) bez za dużo kłopotów?

Nie. Wszystko, co globalnie wystawisz, może zostać zmienione przez użytkownika, to zależy od przeglądarki ograniczają zachowanie javascript:, aby uniknąć oszukania użytkowników, aby uzyskać dostęp do wcześniej przygotowanych linków. Firefox dokonał ostatnio pewnej zmiany w protokole URL javascript.

Jak napisano w tym artykule: http://survey-remover.com/blog/javascript-protocol-dangers/

[[2]} począwszy od Chrome v13, Firefox v6 i IE 9, twórcy przeglądarki zwrócili uwagę na niebezpieczeństwa związane z protokołem " javascript:", a następnie zablokowali kod ... W przypadku Chrome i Np. fragment "javascript:" jest usuwany po wklejeniu kodu, podczas gdy Firefox nie wykonuje już skryptu w zakresie aktywnej strony.
Więc...
Jeśli to niemożliwe, wzruszę ramionami i ruszę dalej.
Powinieneś.
 3
Author: Fagner Brack,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-05 21:54:32

Propozycja

Nie powiem, że jestem ekspertem od tych rzeczy. Ale zakładając, że możesz zawinąć swój kod całkowicie i użyć zdarzeń do wywołania zachowania, możesz użyć struktury takiej jak ta:
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 };

}())};

Ustawiając ją za pomocą obj = Closed("Anything"); możesz nadal mieć złośliwego użytkownika nadpisującego metodę use_secret(), ponieważ jest ona narażona, ale metoda get_secret() i wszelkie inne wewnętrzne elementy są chronione.

Jeśli twoja metoda init deklaruje szereg powiązań zdarzeń z aplikacją, możesz zachować swój stan jako prywatny w tędy. Zdarzenia będą mogły wyzwalać wewnętrzne metody, ponieważ są związane z wewnątrz wewnętrznego zamknięcia, ale Zewnętrzny kod ich nie zobaczy.

Chociaż to może rozwiązać twój problem, nie jestem w 100% pewien, że tak, to i tak nie można mu ufać. Każdy użytkownik, który chce przeniknąć do Twojej aplikacji, może tak długo, jak bezpieczeństwo jest po stronie klienta. Nic ich nie powstrzyma przed stworzeniem własnego obiektu, aby zastąpić twój po fakcie, ES5 lub nie ES5.

Dla wszystkiego, co faktycznie musi być bezpieczne, będziesz musiał uaktualnić po stronie serwera. Nigdy nie ufaj kodowi po stronie klienta, aby cię chronić, żądanie może nie pochodzić nawet ze strony, którą obsługiwałeś ...

 1
Author: Jonas Schubert Erlandsson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-03 15:21:22

Co jeśli is_allowed będzie całkowicie lokalne?

(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 mockup

BTW: w Twoim kodzie {[2] } będzie undefined.

 0
Author: KooiInc,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-04 08:07:15