Возьмите любое из решений, которые следуют шаблону Крокфорда private или priviledged . Например:
function Foo(x) {
var y = 5;
var bar = function() {
return y * x;
};
this.public = function(z) {
return bar() + x * z;
};
}
В любом случае, когда злоумышленник не имеет права «выполнить» в контексте JS, он не имеет доступа к каким-либо «открытым» или «закрытым» полям или методам. В случае, если у злоумышленника есть такой доступ, он может выполнить следующую однострочную строку:
eval("Foo = " + Foo.toString().replace(
/{/, "{ this.eval = function(code) { return eval(code); }; "
));
Обратите внимание, что приведенный выше код является общим для всех типов данных конструктора. Он потерпит неудачу с некоторыми решениями здесь, но должно быть ясно, что почти все решения, основанные на замыканиях, могут быть разбиты таким образом с различными параметрами replace()
.
После этого любой объект, созданный с помощью new Foo()
, будет иметь метод eval
, который можно вызывать для возврата или изменения значений или методов, определенных в замыкании конструктора, например ::
f = new Foo(99);
f.eval("x");
f.eval("y");
f.eval("x = 8");
Единственная проблема, с которой я могу столкнуться, это то, что она не будет работать в тех случаях, когда существует только один экземпляр, и он создается при загрузке. Но тогда нет никакой причины фактически определять прототип, и в этом случае злоумышленник может просто воссоздать объект вместо конструктора, если у него есть способ передать те же самые параметры (например, они являются постоянными или вычисляются из доступных значений).
На мой взгляд, это в значительной степени делает решение Крокфорда бесполезным. Поскольку «конфиденциальность» легко нарушается, недостатки его решения (снижение читабельности и удобства обслуживания, снижение производительности, увеличение памяти) делают «нет конфиденциальность »метод на основе прототипа лучший выбор.
Обычно я использую начальные подчеркивания для обозначения __private
и _protected
методов и полей (стиль Perl), но идея конфиденциальности в JavaScript просто показывает, как это неправильно понимается.
Поэтому я не согласен с Крокфордом , за исключением его первого предложения.
Так как же получить реальную конфиденциальность в JS? Поместите все, что требуется, чтобы быть частным на стороне сервера, и используйте JS для выполнения вызовов AJAX.