Комментарии 35
Мне кажется в последнее время через чур много внимания уделяют «псевдо» плохости глобальных переменных и в «псевдо» удобности отсутствия оных в JS.
+13
Если понимать глобальную переменную как ссылку на модуль — это не плохо, так проще организовывать структуру проекта. Если глобальная переменная как локальная переменная (отсутствие var) — казнить, нельзя помиловать!
Отсутствие глобальных переменных это хорошо из-за соображений безопасности: злоумышленнику гораздо сложнее анализировать код, невозможно вызвать внутренний метод напрямую.
Отсутствие глобальных переменных это хорошо из-за соображений безопасности: злоумышленнику гораздо сложнее анализировать код, невозможно вызвать внутренний метод напрямую.
0
Злоумышленнику сложнее анализировать JavaScript-код, поставляемый в открытом виде?
+2
Про открытый вид я ничего не говорил. Значительно проще анализировать код если ты видишь глобальные переменные/объекты (есть с чего начать). Разве не так?
-1
А ничего что некоторые браузеры не позволяют сделать delete для свойств объекта window?
+1
Досадное упущение, добавил хак для IE.
+1
надеюсь только для IE ниже 9 версии?
И можно узнать какой?
И можно узнать какой?
0
6-8 точно, 9 не установлен
Подробнее perfectionkills.com/understanding-delete/
try {
delete window.ModuleA;
delete window.ModuleС;
} catch (e) { // IE фикс
window.ModuleA = undefined;
window.ModuleС = undefined;
}
Подробнее perfectionkills.com/understanding-delete/
0
Я бы сказал, что отсутствие глобальных переменных осложняет злоумышленнику модификацию вашего кода на машине конечно пользователя.
Т.е. даже если у него есть возможность на странице с вашим кодом (хорошим) выполнить свой код (плохой), то, при отсутствии глобальных переменных в хорошем коде, ему будет сложнее как-то вмешаться в его работу программно из плохого. Если вы будете использовать глобальную jQuery, к примеру, то, модифицировав ее методы, он сможет менять логику работы вашего кода и т.п.
Т.е. даже если у него есть возможность на странице с вашим кодом (хорошим) выполнить свой код (плохой), то, при отсутствии глобальных переменных в хорошем коде, ему будет сложнее как-то вмешаться в его работу программно из плохого. Если вы будете использовать глобальную jQuery, к примеру, то, модифицировав ее методы, он сможет менять логику работы вашего кода и т.п.
+1
Если вы боитесь за сохранность jQuery, то лучше включить её в сборку(будет 1 монолитный js файл).
0
Не поверите, сейчас в _любом_ браузере есть дебаггер, злоумышленник может анализировать код даже без глобальных переменных.
0
Интересная штука, хотя и очень специализированная.
Ну и 3й метод для предотвращения перехватов, ни разу не unobtrusive, к чему стремится остальное, может очистить какие-то нужные таймеры/интервалы.
Писал нечто подобное свое, но там в замыкание собирались все необходимые файлы и все (ну плюс всякие преобразования кода необходимые).
Ну и 3й метод для предотвращения перехватов, ни разу не unobtrusive, к чему стремится остальное, может очистить какие-то нужные таймеры/интервалы.
Писал нечто подобное свое, но там в замыкание собирались все необходимые файлы и все (ну плюс всякие преобразования кода необходимые).
+1
Согласен, правилом должно быть «не трогать глобальные переменные». Если кто-то юзает до тебя таймеры значит это ему нужно и таким действием можно только всё сломать.
Тоже самое и удалять за собой глобальные объекты. Если они какое-то время видны, а потом их нестало это совсем не тоже самое что «их небыло». Даже на времени жизни этих переменных от объявления до удаления может произойти всё что угодно. И это не считая того, что уже при объявлении имена могли совпасть с чем-то существующим.
В целом я за использование своего собственного неймспейса при необходимости работать с глобальными переменными. Это наиболее безопасный и правильный способ.
Тоже самое и удалять за собой глобальные объекты. Если они какое-то время видны, а потом их нестало это совсем не тоже самое что «их небыло». Даже на времени жизни этих переменных от объявления до удаления может произойти всё что угодно. И это не считая того, что уже при объявлении имена могли совпасть с чем-то существующим.
В целом я за использование своего собственного неймспейса при необходимости работать с глобальными переменными. Это наиболее безопасный и правильный способ.
0
Насчет убийства таймеров я с вами могу не согласиться. Если вы применяете эту технику, значит вам есть от чего защищаться (юзерскрипты и расширения которые работают с вашей страницей), поэтому убив чужие таймеры вы только улучшите вашу защиту.
Учитывайте, что в статье описана сборка для Production.
Если они какое-то время видныОни видны только скрипту во время первичного его скрипта. Они не видны до и не видны после отработки скрипта. Зачем их оставлять, если вы знаете, что их ничего и никто(разработчик) не будет испльзовать?
Учитывайте, что в статье описана сборка для Production.
0
Что делать в случае, если методы таймеров были переопределены каким-то скриптом?
Или здесь обязательно оговорка, что этот скрипт отрабатывает 100% всегда первым?
Или здесь обязательно оговорка, что этот скрипт отрабатывает 100% всегда первым?
0
Или здесь обязательно оговорка, что этот скрипт отрабатывает 100% всегда первым?Нет.
Что делать в случае, если методы таймеров были переопределены каким-то скриптом?Вот простейший способ определить это:
/\s*\[native code]/.test(window.setTimeout);
Однако злоумышленник может сделать вот так и испортить всю малину:
RegExp.prototype.test = function () {return 4};
Дальше это уже другая история. У меня есть другой проект, в котором есть функции isNativeFunction, которые не используют RegExp#test.
Я специально не стал включать функции защиты от перехвата переменных в текущую версию — они требуют дополнительной работы.
0
window.clearInterval= frame.contentWindow.clearInterval
0
Предположим, что мы получили потенциально чистый setInterval via:
1. setInterval текущего окна и фрэйма имеют разные счетчики таймеров. Это не такая уж и беда.
2. Мы не защищены от перехвата фрэйма во время вставки в DOM (при вставке в DocumentFragment frame не создает окно).
3. Думаю, что так или иначе можно отравить и
Единственное, что не может переопределить пользователь это поведение операторов, на них и стоит в первую очередь опираться.
var fr = document.createElement('iframe');
fr.src='about:blank';
document.body.appendChild(fr);
fr.contentWindow.setInterval
1. setInterval текущего окна и фрэйма имеют разные счетчики таймеров. Это не такая уж и беда.
2. Мы не защищены от перехвата фрэйма во время вставки в DOM (при вставке в DocumentFragment frame не создает окно).
3. Думаю, что так или иначе можно отравить и
frame.contentWindow.clearInterval/setInterval
в about:blank
Единственное, что не может переопределить пользователь это поведение операторов, на них и стоит в первую очередь опираться.
0
Ерундой занимаетесь по моему. Безопасность в JS отсутствует по причине наличия прототипов. Можно в легкую переопределить прототипы всех базовых классов (типа String, Array и остальных), а в методах реализовать все что угодно, и даже (о чудо) такое:
Попробуйте создать фрейм через document.createElement.
Правильно применив такой «взлом», внести вредоносный код в ваше приложение будет несложной задачей.
(function(method) {
for (var method in document) {
(function(method) {
var toString = document[method] + "";
document[method] = function() {
alert("Ня");
};
document[method].toString = function() { return toString; };
document[method].toSource = function() { return toString; };
})(method);
}
})();
Попробуйте создать фрейм через document.createElement.
Правильно применив такой «взлом», внести вредоносный код в ваше приложение будет несложной задачей.
0
Запустил, то что написал. Поправка:
<code> (function(method) { for (var method in document) { if (typeof document[method] != "function") { continue; } (function(method) { var toString = document[method] + ""; document[method] = function() { alert("Ня"); }; document[method].toString = function() { return toString; }; document[method].toSource = function() { return toString; }; })(method); } })(); </code>
0
Я вкурсе, что можно сломать все. Единственное, что не может сломать пользователь напрямую из скрипта — UserAgent (не опера) и примитивные операторы.
Задача же isNativeFunction состоит в том, чтобы выяснить были ли переопределены методы и оповестить об этом наблюдателя (дальше основная логика скрипта не будет выполнена). Про toString и toSource и прочие я, конечно, знаю и с этим можно бороться.
Прототип isNativeFunction точно работает в FF. Взломом будет считаться переопределение toString, hasOwnProperty, присутствие toString у метода и прочие подозрительные операции, которые обычный пользователь не будет писать в любом случае.
Задача же isNativeFunction состоит в том, чтобы выяснить были ли переопределены методы и оповестить об этом наблюдателя (дальше основная логика скрипта не будет выполнена). Про toString и toSource и прочие я, конечно, знаю и с этим можно бороться.
Прототип isNativeFunction точно работает в FF. Взломом будет считаться переопределение toString, hasOwnProperty, присутствие toString у метода и прочие подозрительные операции, которые обычный пользователь не будет писать в любом случае.
function isNativeFunction(functionSource, functionName) {
var nativeCodeToString = (function(){
if (window.opera || typeof /./ === 'function') { // Op Ch fix
return 'function toString() { [native code] }';
}
return 'function toString() {\n [native code]\n}';
}()),
nativeCodeFunction = (function(){
if (window.opera || typeof /./ === 'function') { // Op Ch fix
return 'function ' + functionName + '() { [native code] }';
}
return 'function ' + functionName + '() {\n [native code]\n}';
}()),
nativeCodeHasOwnProperty = (function(){
if (window.opera || typeof /./ === 'function') { // Op Ch fix
return 'function ' + functionName + '() { [native code] }';
}
return 'function hasOwnProperty() {\n [native code]\n}';
}());
return (functionSource.toString + '' === nativeCodeToString) &&
(functionSource.hasOwnProperty + '' === nativeCodeHasOwnProperty) &&
(functionSource + '' === nativeCodeFunction) &&
(!functionSource.hasOwnProperty('toString')) &&
(Function.prototype.toString + '' === nativeCodeToString) &&
(Function.prototype.toString === Function.toString) &&
(!Function.prototype.toString.hasOwnProperty('toString')) &&
(Object.prototype.toString + '' === nativeCodeToString) &&
(!Object.prototype.toString.hasOwnProperty('toString')) &&
(typeof Function === 'function') &&
(typeof Object === 'function');
};
0
Вы не только защититесь, но и сломаете юзерскрипты/расширения. Это конечно метод защиты, но крутоват.
> Они не видны до и не видны после отработки скрипта
Но они могут перетереть глобальные других скриптов с такими же названиями.
Лучше все же сразу при сборке собирать все в одно замыкание и все.
> Они не видны до и не видны после отработки скрипта
Но они могут перетереть глобальные других скриптов с такими же названиями.
Лучше все же сразу при сборке собирать все в одно замыкание и все.
0
Пожалуйста, не называйте всё и всех «ниндзя»-производными. Это «звание» нужно заслужить, не присвоить.
+1
Обычно вполне устраивает использование нейспейсов, например в YUI библиотеки YAHOO.util.Dom, YAHOO.lang и тд. Иногда проще сделать проще, чем потом производить в ранг нинзя другого человека.
Но в любом случае JS это занимательно, всегда есть куда применить здоровые и не очень идеи :)
Но в любом случае JS это занимательно, всегда есть куда применить здоровые и не очень идеи :)
0
Я ни в коем случае не пропагандирую затруднение разработки во благо скрытия глобалов just for fun.
В статье была показана сборка проекта для среды Production — там потенциальные злоумышленники от которых мы хотим защититься, затрудняя reverse engineering и скрывая глобалы. Для среды Deveopment вы можете создать свою сборку с открытыми глобалами.
В статье была показана сборка проекта для среды Production — там потенциальные злоумышленники от которых мы хотим защититься, затрудняя reverse engineering и скрывая глобалы. Для среды Deveopment вы можете создать свою сборку с открытыми глобалами.
0
Оффтопик:
Ниндзя — это шпионы. Их задачи, в основном — шпионаж и убийства. Ваша библиотека — скорее контрразведка, борьба со шпионами врага. Думаю, что круче было бы назвать тулзу KGBjs или NKVDjs (FSBjs, как вариант)
Ниндзя — это шпионы. Их задачи, в основном — шпионаж и убийства. Ваша библиотека — скорее контрразведка, борьба со шпионами врага. Думаю, что круче было бы назвать тулзу KGBjs или NKVDjs (FSBjs, как вариант)
0
var $my= { _my: $my }
with( $my ){
$my.$= function( id ){
return document.getElementsById( id )
}
}
with( $my ){
$my.hide= function( id ){
$( id ).style.visibility= 'hidden'
}
}
$my= $my._my
объявлять модули можно в любом порядке, сторонний код не замечает нашего присутствия. а от «ух, злобных хакеров» всё-равно не защититься, так что не будем страдать маразмом и дропать все таймеры и прочая
with( $my ){
$my.$= function( id ){
return document.getElementsById( id )
}
}
with( $my ){
$my.hide= function( id ){
$( id ).style.visibility= 'hidden'
}
}
$my= $my._my
объявлять модули можно в любом порядке, сторонний код не замечает нашего присутствия. а от «ух, злобных хакеров» всё-равно не защититься, так что не будем страдать маразмом и дропать все таймеры и прочая
+1
Зарегистрируйтесь на Хабре , чтобы оставить комментарий
Сборка проекта без единой глобальной переменной