Microsoft.com изнутриУправление и делегирование ASP.NET

Джефф Тоуз (Jeff Toews)

Инфраструктура веб-узла microsoft.com в основном построена на базе .NET Framework 2.0.Одна из наиболее сложных административных задач команды поддержки веб-узла microsoft.com заключается в настройке конфигурации ASP.NET. Стремясь сделать нашу конфигурацию идеальной, мы научились очень многому. Чтобы

правильно понять параметры конфигурации, требуется практический опыт работ с разделами конфигурации в файлах web.config и machine.config и понимание значения этих параметров. Примеры помогут вам лучше понять настройки этих параметров и их важность. В этой статье я дам несколько советов по настройке конфигурации, основанных на нашем опыте работы с серверами веб-узла microsoft.com, чтобы вы могли использовать наш опыт с пользой для себя.

1. Как правильно настроить параметры компиляции

При внедрении приложений на базе ASP.NET очень важно убедиться, что никто случайно (или специально) не оставил для атрибута отладки значение true во всех файлах настройки конфигурации web.config, как показано ниже:

<compilation debug="true" />

В сложных инфраструктурах с большим числом веб-приложений желательно предотвратить это, используя механизм управления конфигурацией ASP.NET. (Чуть позднее я предоставлю более подробную информацию по этому вопросу).

Также очень важно убедиться, что атрибуты отладки для отдельных страниц не имеют значение true в отдельных файлах .aspx, как показано здесь:

<%@ Page debug="true" %>

Естественно, при работе с крупными веб-узлами, на которых размещается большой объем информации, нельзя ожидать, что вы сможете проверить удаление этого параметра со всех страниц .aspx до их публикации. Для предотвращения этого требуются средства глобального характера.

При компиляции веб-приложений с такими параметрами получаются отладочные, а не финальные файлы. Кроме того, код не оптимизируется, в результате чего снижается производительность. Время ожидания запросов ASP.NET не истекает, поскольку параметры отладки не дают ему истечь. Отладочная версия приложения в рабочей среде – открытая дверь для хакера!

К счастью, в Microsoft® .NET Framework 2.0 имеется новый параметр внедрения для файла machine.config, при использовании которого в ASP.NET отключается следующее: функции отладки, отслеживание вывода и отображение сообщений об ошибках ASP.NET (как на локальной системе, так и удаленных) вне зависимости от настроек в файле web.config file и атрибутов страниц. Этот параметр выглядит следующим образом:

<configuration>
    <system.web>
          <deployment retail="true"/>
    </system.web>
</configuration>

Обратите внимание, что последние два преимущества (отключение отслеживания вывода и подробных сообщений об ошибках ASP.NET) представляют собой передовые методики безопасности, которые настоятельно рекомендуется применять. Если их не применять, все внутренние конструкции вашего приложения станут уязвимыми для всех желающих.

Также следует упомянуть об одном важном факте: блокировка атрибута отладки <system.web><compilation> в корневом файле web.config в <location allowOverride="false"> или использование атрибута lockItems attribute не даст файлам web.config более низкого уровня иерархии конфигурации приложения включить параметры отладки. Однако это не помешает отдельным страницам .aspx включить режим отладки в их атрибутах страницы. Использование параметра retail при внедрении – единственный способ полностью отключить все функции отладки ASP.NET на всех уровнях.

Установка значения true для параметра retail - самый лучший способ, который следует применять компаниям, использующим отдельные серверы для рабочих версий, чтобы обеспечить оптимальную производительность и отсутствие уязвимых мест в области безопасности. Как я уже говорил, этот новый параметр появился только в ASP.NET 2.0, куда он был включен благодаря отзывам и предложениям, полученным рабочей группой ASP.NET.

В средах, которые используются для предварительного тестирования и отладки, параметр retail использовать не следует. В корневом файле web.config предварительной среды следует установить параметр <compilation debug="false"> и дать файлам web.config отдельных приложений и атрибутам страниц .aspx приоритет по отношению к корневому файлу.

2. Использование среднего уровня доверия в ASP.NET 2.0

Как это сделали мы для многих узлов microsoft.com, подумайте о возможностях использования среднего уровня доверия после переноса своего узла или приложений на платформу ASP.NET 2.0, если сейчас вы используете полный или высокий уровень доверия. Например, ограничение WebPermission ограничивает связь приложения только с одним адресом или диапазоном адресов, определяемых через элемент <trust>. Это позволит вам контролировать и поддерживать список внешних узлов и диапазонов адресов, вызов которых может осуществляться удаленно. Это очень большой плюс с точки зрения безопасности.

Также ограничено и разрешение FileIOPermission. Это означает, что код приложения может иметь доступ только к файлам в виртуальной иерархии каталогов. При используемом по умолчанию среднем уровне доверия каждое приложение получает разрешения Read, Write, Append и PathDiscovery только для виртуальной иерархии каталогов. Это означает прекращение случайного доступа к файлам, что очень важно для общих веб-инфраструктур, в которых развернуто много приложений.

Еще одно преимущество заключается в удалении привилегий неуправляемого кода. Это означает, что вы можете предотвратить использование стандартных компонентов, что является самым простым способом отключить использование атрибута страницы Aspcompat. (Если атрибут Aspcompat включен, производительность страницы может упасть).

Средний уровень доверия ASP.NET 2.0 отличается достаточной гибкостью, позволяя администратору создавать исключения для всех ранее установленных стандартных ограничений. В ASP.NET 1.1 такой гибкости не было. Еще одна причина использования среднего уровня доверия в ASP.NET 2.0 заключается в возможности доступа к базам данных Microsoft SQL Server™.

Таким образом, если на одном сервере размещено несколько приложений, вы можете использовать средства защиты кода и средний уровень доверия для изоляции приложений. Установив и заблокировав уровень доверия (с помощью тегов <location allowOverride="false">) в корневом файле root web.config, вы можете установить политики безопасности для всех веб-приложений на сервере. Как показано на Рисунке 1, параметр allowOverride="false" позволяет разработчику запретить снятие приоритета политики среднего уровня доверия, установленной в файле web.config.

Figure 1 Настройки уровня доверия

<configuration>
    <location allowOverride="false">
        <system.web>
            <securityPolicy>
                <trustLevel name="Full" policyFile="internal" />
                <trustLevel name="High" policyFile="web_hightrust.config" />
                <trustLevel name="Medium" policyFile="web_mediumtrust.config" />
                <trustLevel name="Low"  policyFile="web_lowtrust.config" />
                <trustLevel name="Minimal" policyFile="web_minimaltrust.config" />
            </securityPolicy>
            <trust level="Medium" originUrl="" />
        </system.web>
    </location>
</configuration>

Более подробную информацию об использовании среднего уровня доверия в ASP.NET 2.0 можно найти в следующей статье: "Как использовать средний уровень доверия в ASP.NET 2.0".

3. Ограничение загрузки определенных типов файлов

Несомненно, на вашем сервере есть файлы, которые не должны попасть в чужие руки. К счастью, в ASP.NET по умолчанию установлены перехват и блокировка запросов отдельных типов файлов, используемых в приложениях ASP.NET. В их число входят файлы .config и .cs, где хранится исходный код приложения. ASP.NET обеспечивает конфиденциальность этих файлов, связывая оба типа файлов с обработчиком System.Web.HttpForbiddenHandler. При вызове этот обработчик выдает сообщение об ошибке пользователю, запрашивающему файл. Этот метод можно использовать для ограничения доступа к файлам любого типа.

Например, на веб-узле microsoft.com доступ к файлам .asmx запрещен посредством добавления следующего кода в раздел <system.web><httpHandlers> файла root web.config:

<add path="*.asmx" verb="*" type=
    "System.Web.HttpForbiddenHandler" />

Как видите, вы можете использовать теги <add> в элементе <httpHandlers>, чтобы указать дополнительные типы файлов для блокировки. Установите атрибут действия "*". Таким способом вы укажете, что для данного типа файла следует блокировать все типы запросов HTTP. Определите атрибут пути, как подстановочный символ, соответствующий типу файлов, которые вы хотите заблокировать. Например, вы можете использовать "*.mdb". Также вы можете установить атрибут типа "System.Web.HttpForbiddenHandler".

4. Аккуратно добавляйте ссылки на блоки

На каждом веб-сервере .NET имеется кэш для машинного кода, называемый Global Assembly Cache (GAC). В кэше GAC хранятся блоки, совместно используемые несколькими приложениями на компьютере. В GAC рекомендуется добавлять блоки, если отдельным приложениям требуются ссылки на эти блоки, даже если большинство узлов веб-сервера их не использует. При этом не происходит значительного снижения производительности, однако обеспечивается централизованный контроль версий, а не распределение общих блоков по серверу в папках /bin отдельных приложений.

Критерий, согласно которому ссылки на блоки следует добавлять в корневой файл web.config, должен быть намного более жестким, чем критерий, определяющий, когда блоки помещаются в GAC. Когда отдельные приложения добавляют в свои файлы web.config ссылки на блоки, не являющиеся глобальными, производительность становится намного выше, чем при декларировании этих ссылок в корневом файле web.config. Время загрузки страницы значительно уменьшается для всех приложений на сервере, которые не используют эти блоки, поскольку компилятору не приходится тратить время на загрузку ненужных блоков. Компилятор ASP.NET не загружает блоки приложений просто из-за того, что они блоки находятся в GAC. Он загружает их только если в области приложения существует ссылка на эти блоки. В связи с этим в корпорации microsoft.com разработчикам приложений разрешено устанавливать приоритет для элемента <configuration><system.web><compilation><assemblies> в файлах web.config своих приложений для всех частей инфраструктуры Microsoft.com.

В частности, в корневых файлах web.config в рабочей инфраструктуре и в демонстрационной инфраструктуре microsoft.com все атрибуты узла <system.web><compilation> заблокированы (включая атрибуты debug, explicit, defaultLanguage), равно как и все его элементы (buildProviders, expressionBuilders, и др.), за исключением элемента <assemblies>:

<compilation debug="false" 
    explicit="true" defaultLanguage="vb" 
    numRecompilesBeforeAppRestart="500" 
    lockAttributes="*" lockAllElementsExcept=
        "assemblies" >

В среде предварительного тестирования раздел <system.web><compilation> заблокирован в корневом файле web.config, но разработчики приложений могут снимать приоритет элемента <assemblies> и снимать приоритет debug="false" (для целей отладки и устранения неисправностей):

<compilation debug="false" explicit="true"
    defaultLanguage="vb" 
    numRecompilesBeforeAppRestart="500" 
    lockAllAttributesExcept="debug" 
    lockAllElementsExcept="assemblies" >

Обратите внимание на использование атрибутов блокировки, которые являются новыми в ASP.NET 2.0. Подробную информацию по этим атрибутам и примерам их использования можно найти на странице "Общие атрибуты, унаследованные элементами раздела".

5. Удаление установленных значений MaxConnection вручную

Почти на всех веб-узлах microsoft.com используются приложения ASP.NET, которые выполняют вызовы удаленных кластеров веб-служб. Максимальное число одновременных удаленных вызовов веб-служб с одного веб-сервера определяется атрибутом maxConnection элемента <connectionManagement> в файле machine.config. По умолчанию в ASP.NET 1.1 для параметра maxConnection установлено значение 2. Это старое значение по умолчанию для параметра maxConnection слишком низкое для таких узлов, как microsoft.com, на которых одновременно работают сотни приложений, вызывающих удаленные процедуры. В результате запросы ASP.NET помещались в очередь, ожидая завершения вызовов удаленных веб-служб. (Вы можете просмотреть число запросов ASP.NET в очереди с помощью счетчика perfmon ASP.NET\Requests Queued).Чтобы обеспечить возможность одновременного выполнения большего числа вызовов удаленных веб-служб и соответственно повысить производительность приложений узла, мы увеличили значение maxConnection до 40 для наших четырехпроцессорных веб-серверов. (Обычно рекомендуется устанавливать значение параметра maxConnection, равное двенадцатикратному числу процессоров, однако это также зависит от конкретной ситуации).

В ASP.NET 2.0 больше не требуется устанавливать значение параметра maxConnection вручную, поскольку оно масштабируется и устанавливается автоматически. Это связано с функционированием нового раздела конфигурации для элемента processModel в файле machine.config (более подробную информацию об элемента processModel можно найти на странице "processModel Element (Схема параметров ASP.NET))".

<system.web>
    <processModel autoConfig="true" />
</system.web>  

Если в файле machine.config включен параметр autoConfig (по умолчанию), ASP.NET устанавливает для параметра maxConnection значение 12n (где n - число процессоров в системе). При включении параметра autoConfig также происходит следующее: Для параметров maxWorkerThreads и maxIoThreads устанавливается значение 100, для параметра minFreeThreads устанавливается значение 88n, для параметра minLocalRequestFreeThreads устанавливается значение 76n, а для параметра minWorkerThreads устанавливается значение 50.

Прежде чем использовать параметр autoConfig в ASP.NET 2.0 для автоматического определения и настройки значений для параметра maxConnection и других атрибутов, обязательно удалите установленные вручную значения этих параметров, поскольку эти значения будут использоваться вместо значений autoConfig. Об этом нужно помнить при переходе с ASP.NET 1.1, где значение maxConnection нужно прямо указывать, на ASP.NET 2.0, где имеется значение по умолчанию.

Значения параметра autoConfig для maxConnection и других перечисленных атрибутов являются некоторым образом произвольными и могут работать не для всех случаев, однако, насколько мне известно, все эти ограничения отлично работают практически для всех приложений microsoft.com.

Если вы решите настроить параметр maxConnection вручную, будьте осторожны при его увеличении, поскольку оно приведет к повышению нагрузки на процессор. Увеличение нагрузки связано с тем, что ASP.NET обрабатывает больше входящих запросов, не заставляя их ожидать очереди вызова веб-службы. Разумеется, нужно помнить, что атрибут maxConnection не влияет на вызов локальных веб-служб, а влияет только на вызов удаленных веб-служб.

6. Помните о необработанных исключениях

При переносе веб-узлов и приложений ASP.NET 1.1 на платформу ASP.NET 2.0, очень важно помнить о значительном изменении установленной по умолчанию политики для необработанных исключений. В .NET Framework 1.1 и 1.0 необработанные исключения на управляемых потоках игнорировались и, поскольку приложения продолжали работать, эти исключения часто оставались скрытыми. Если вы не использовали отладчик для поиска исключений, вы могли даже не знать об их существовании. Однако в ASP.NET 2.0 при возникновении необработанного исключения приложение ASP.NET может неожиданно прекратить работу. Это может серьезно повлиять на доступность вашего узла или приложения при возникновении большого числа необработанных исключений, которые ранее регулировала стандартная политика.

Лучший способ решения этой проблемы заключается в выполнении тщательного тестирования и уничтожении необработанных исключений (которых вообще то не должно быть в вашем приложении). Однако в случае переноса очень больших приложений или большого числа приложений тщательное тестирование может оказаться затруднительным, и в этом случае у вас есть еще два варианта решения проблемы. При переносе веб-узла microsoft.com на платформу ASP.NET 2.0 мы установили стандартную политику для необработанных исключений, используемую в ASP.NET 1.1 и ASP.NET 1.0.

Чтобы включить стандартную политику обработки исключений нужно добавить в файл aspnet.config следующий код:

<configuration>
    <runtime>
        <legacyUnhandledExceptionPolicy 
            enabled="true" />
    </runtime>
</configuration>

Код находится в следующих двух папках:

%WINDIR%\Microsoft.NET\Framework\v2.0.50727 (в системах x86 или SYSWOW64) и %WINDIR%\Microsoft.NET\Framework64\v2.0.50727 (в системах x64).

В результате этого изменения будет восстановлено стандартное поведение .NET Framework в версиях 1.1 и 1.0. Считайте это краткосрочным решением проблемы, поскольку оно просто скрывает ошибки вашего приложения. Однако этот способ все равно очень полезен для избежания проблем с доступностью в связи с неожиданным прекращением работы процессов. Более подробную информацию об изменении поведения можно найти на странице "Необработанные исключения вызывают непредвиденное завершение работы приложений ASP.NET в .NET Framework 2.0".

7. Обеспечение правильной настройки конфигурации прокси-сервера

Администратор веб-сервера может указать необходимость использования прокси-сервера для обращений к Интернету через протокол http, настроив элемент <configuration><system.net><defaultProxy> в файле machine.config.

В рабочей среде microsoft.com мы настроили параметр <defaultProxy> для использования системного значения по умолчанию default proxy (поскольку клиент брандмауэра не установлен), и мы используем теги <location allowOverride="false"> для предотвращения отмены приоритета элемента <defaultProxy> разработчиками приложений (которые могут случайно опубликовать файл web.config с внутренним прокси-сервером):

<configuration>
    <location allowOverride="false">
       <system.net>
          <defaultProxy>
              <proxy usesystemdefault="true" />
          </defaultProxy>
       </system.net>
    </location>
</configuration>

В предварительной и демонстрационной средах microsoft.com мы устанавливаем для атрибута usesystemdefault значение, устанавливаем для атрибута bypassonlocal значение true и добавляем список proxy bypasslist (см. Рисунок 2). В списке bypasslist перечислены регулярные выражения, описывающие адреса, которые не используют указанный прокси-сервер. Этот раздел заключен в теги <location allowOverride="false">, благодаря чему разработчики не могут указать собственный прокси сервер в файле web.config. (Эти прокси-серверы обычно являются внутренними, и вызов этих серверов прекращается при переносе страниц в рабочую среду). При попытках указать прокси-сервер в предварительной или демонстрационной среде возникнет ошибка ASP.NET, и разработчики будут должны удалить эту конфигурацию перед публикацией.

Figure 2 Настройка списка Bypasslist

<configuration>
    <location allowOverride="false">
        <system.net>
             <defaultProxy>
                <proxy
usesystemdefault="false"
proxyaddress = "http://proxy.server.foo.com:80"
bypassonlocal = "true" />

                <bypasslist>
<add address="10\.*"/>
<add address="dns\.foo\.com" />
<add address="name1\.name2\.foo\.com" />
                </bypasslist>
            </defaultProxy>
        </system.net>
    </location>
</configuration>

8. Не делайте ошибки доступными для всех

Как я уже говорил, очень важно не разрешать веб-серверам в рабочей среде выдавать подробные сообщения об ошибках ASP.NET удаленно.

В файлах web.config рабочей и демонстрационной среды microsoft.com, атрибут режима <configuration><system.web><customErrors> имеет значение RemoteOnly, в связи с чем ошибки приложения показываются удаленным клиентам, а ошибки ASP.NET доступны на локальной системе (чтобы облегчить диагностику и устранение неисправностей администраторами веб-серверов). Обратите внимание, что элемент <customErrors> находится внутри тегов <location> tag with allowOverride="false" (см. Рисунок 3). Это позволяет предотвратить владельцам отдельных приложений случайно или преднамеренно установить режим "Off" и сделать подробные сообщения об ошибках ASP.NET доступными через Интернет.

Figure 3 Предотвращение вывода сообщений об ошибках

&lt;configuration&gt;
    &lt;location allowOverride='false'&gt;
        &lt;system.web&gt;
            &lt;customErrors mode='RemoteOnly' defaultRedirect=
                   '/errorpages/generic_customerror.aspx'&gt;
                &lt;error statusCode='404' redirect='/errorpages/filenotfound_customerror.aspx' /&gt;
            &lt;/customErrors&gt;
        &lt;/system.web&gt;
    &lt;/location&gt;
&lt;configuration&gt;

Также не забывайте, что, как я говорил ранее, параметр <deployment retail="true"/> в файле machine.config отключает отображение подробных ошибок ASP.NET как на удаленных клиентах, так и локально. Используйте параметр retail в качестве основного метода отключения этих сообщений об ошибках в ASP.NET 2.0. (Чтобы получить подробную информацию об исключениях ASP.NET, используйте журнал событий приложения).

В корневом файле web.config предварительной среды microsoft.com, атрибут режима <customErrors> имете значение off, и ошибки ASP.NET отображаются как для локальных, так и для удаленных клиентов. Это обеспечивает возможности отладки, диагностики и устранения неисправностей. Также не настраивается никаких страниц с сообщениями об ошибками приложений:

<configuration>
    <location allowOverride="false">
        <system.web>
            <customErrors mode="Off" />
        </system.web>
    </location>
<configuration>

9. Знайте, когда включать отслеживание

Следы ASP.NET генерируются при выполнении страниц ASP.NET. В них содержатся интересные данные о запросе, дереве управления страницей и выполнении различных этапов цикла управления страницей и элементов управления страницей. Кроме того, возможно написание сообщений для отслеживания страниц. Следы могут добавляться к данным, выводимым отслеживаемой страницей, в качестве части списка отслеживаемых запросов в средстве отслеживания работы приложения. Эта функция обычно требуется для отладки в предварительной среде и не должна использоваться в рабочей среде.

В корневых файлах web.config в рабочей и демонстрационной средах microsoft.com атрибут <configuration><system.web><trace> enabled имеет значение "false", т.е. возможность вывода информации отслеживания для веб-страниц отключена. Обратите внимание, что элемент <trace> находится внутри тегов <location> со значением allowOverride="false". Это позволяет предотвратить владельцам отдельных приложений случайно или преднамеренно установить параметр enabled="true" и сделать подробную информацию об отслеживании ASP.NET доступной через Интернет:

<configuration>
    <location allowOverride="false">
        <system.web>
              <trace enabled="false" localOnly="true"
              pageOutput="false" requestLimit="10" traceMode="SortByTime" />
        </system.web>
    </location>
<configuration>

<system.web><trace>

Как я говорил ранее, параметр <deployment retail="true"/> в файле machine.config отключает вывод результатов отслеживания ASP.NET для веб-страницы. Используйте параметр retail в качестве основного метода отключения данных отслеживания при использовании .NET Framework 2.0.

Для полной уверенности в невозможности случайного включения отслеживания в рабочей среде, доступной для внешнего мира, разработчики microsoft.com удаляют обработчик trace.axd из корневого файла web.config или преобразовывают его в комментарий, как показано ниже:

<!--
<add path="trace.axd" verb="*" type=
    "System.Web.Handlers.TraceHandler"
    validate="True" />
-->

10. Отключение модуля Session State для ферм серверов

Поскольку все веб-узлы microsoft.com объединены в кластер с помощью системы сетевой балансировки нагрузки (NLB) с равномерным распределением запросов на всех серверах кластера, не существует никаких гарантий относительно того, что все запросы какого-то приложения будет обрабатывать один и тот же сервер . В результате этого модуль ASP.NET Session State отключен, чтобы разработчики не могли использовать свойство Session. Разработчикам приложений, желающим иметь данные о состоянии, мы рекомендуем использовать элемент View State для сохранения данных состояния в структуре кода страницы, так, чтобы не занимать серверные ресурсы.

Для отключения Session State на веб-сервере нужно удалить соответствующий дочерний узел узла <httpModules>:

<add name="Session" type=
    "System.Web.SessionState.
    SessionStateModule"/>

Я предположил, что вы уже видели и даже использовали файлы конфигурации ASP.NET (machine.config, корневой файл web.config и файлы приложений web.config), но если вы с ними еще не знакомы, воспользуйтесь кратким учебником по ASP.NET: asp.net/QuickStart/aspnet/doc/management/fileformat.aspx.

В статье также говорится, что в систему конфигурации ASP.NET 2.0 входит ряд полезных функций, позволяющих администраторам блокировать отдельные элементы и атрибуты конфигурации, используя атрибуты lockItems и lockCollections. Подробную информацию об этих атрибутах и их использовании можно найти в статье "Общие атрибуты, наследуемые элементами разделов".

Джефф Тоуз (Jeff Toews) – менеджер по системному проектированию, работает в команде поддержки Microsoft.com в Редмонде (штат Вашингтон) уже шесть лет. Если у вас возникнут технические вопросы или замечания, вы можете связаться с ним по адресу mscomblg@microsoft.com.

© 2008 Корпорация Майкрософт и компания CMP Media, LLC. Все права защищены; полное или частичное воспроизведение без разрешения запрещено.