Суббота, 13 октября 2012 02:45

Глобальный кэш сборок

Оцените материал
(14 голосов)

Глобальный кэш сборок

Теперь мы умеем создавать сборки со строгим именем - пора узнать, как развертывают такие сборки и как CLR использует метаданные для поиска и загрузки сборки.

 

Если сборка предназначена для совместного использования несколькими приложениями, ее нужно поместить в общеизвестный каталог, который среда CLR должна автоматически проверять, обнаружив ссылку на сборку. Место, где располагаются совместно используемые сборки, называют глобальным кэшем сборок (global assembly cache, GAC). Обычно это каталог C:\Windows\ Assembly (предполагается, что система Windows установлена в каталог C:\Windows).

GAC обладает особой структурой и содержит множество вложенных ката­ логов, имена которых генерируются по определенному алгоритму. Ни в коем случае не следует копировать файлы сборок в GAC вручную - вместо этого надо использовать инструменты, созданные специально для этой цели. Эти инструменты «знают» внутреннюю структуру GAC и умеют генерировать над­ лежащие имена подкаталогов.

В период разработки и тестирования сборок со строгими именами для установки их в каталог GAC чаще всего применяют инструмент GACUtil.exe. Запущенный без параметров, он отобразит следующие сведения:

{codecitation class="brush: plain; gutter: true;" width="100%" }Microsoft (R) .NET Global Assembly Cache Utility. Version 4.0.20928.1 Copyright (с) Microsoft Corporation. All rights reserved.

Usage: Gacutil <command> [ <options> ]
Commands:
/i <assembly_path> [ /r < ...>] [ /f ] Installs an assembly to the global assembly cache.

/il <assembly_path_list_file> [ /r < ...>] [ /f ] Installs one or more assemblies to the global assembly cache.

/u <assembly_display_name> [ /r < ...>] Uninstalls an assembly from the global assembly cache.

/ul <assembly_display_name_list_file> [ /r < ...>] Uninstalls one or more assemblies from the global assembly cache.

/l [ <assembly_name> ] List the global assembly cache filtered bу <assembly_name>

/lr [ <assembly_name> ] List the global assembly cache with all traced references.

/cdl Deletes the contents of the download cache

/ldl Lists the contents of the download cache

/? Displays а detailed help screen

Options:
/r <reference_scheme> <reference_id> <description> Specifies
а traced reference to install (/I, /il) or uninstall (/u, /ul).

/f Forces reinstall of an assembly.

/nologo Suppresses display of the logo banner

/silent Suppresses display of all output{/codecitation}

Вызвав утилиту GACUtil.exe с параметром /i, можно установить сборку в каталог GAC, а если задать параметр /u, сборка будет удалена из GAC. Обратите внимание, что сборку с нестрогим именем нельзя поместить в GAC. Если передать GACUtil.exe файл сборки с нестрогим именем, утилита выдаст следующее сообщение об ошибке (ошибка добавления сборки в кэш: попытка установить сборку без строгого имени):

{codecitation class="brush: plain; gutter: true;" width="100%" }Failure adding assembly to the cache: Attempt to install an assembly without а strong name{/codecitation}

Примечание. По умолчанию манипуляции с каталогом GAC могут осуществлять лишь члены группы Wiпdows Admiпistrators (администраторы) или Power Users (опытные пользователи). GACUtil.exe не сможет установить или удалить сборку, если вызвавший утилиту пользователь не входит в эту группу.

Параметр /i утилиты GACUtil.exe очень удобен для разработчика во время тестирования. Однако при использовании GACUtil.exe для развертывания сборки в рабочей среде рекомендуется применять параметр /r в дополнение к /i - при установке и /u - при удалении сборки. Параметр /r обеспечивает интеграцию сборки с механизмом установки и удаления программ Windows. В сущности, утилита, вызванная с этим параметром, сообщает системе, для какого приложения требуется эта сборка, и связывает ее с ним.

Примечание. Если сборка со строгим именем упакована в САВ-файл или сжата иным способом, то, прежде чем устанавливать файл сборки в каталог GAC при помощи утилиты GACUtil.exe, следует распаковать его во временный файл, который нужно удалить после установки сборки.

Утилита GACUtil.exe не входит в состав свободно распространяемого пакета NET Framework, предназначенного для конечного пользователя. Если в приложении есть сборки, которые должны развертываться в каталоге GAC, используйте программу Windows Installer (MSI), так как это единственный инструмент, способный установить сборки в GAC и гарантированно присутствующий на машине конечного пользователя.

Примечание. Глобальное развертывание сборки путем размещения ее в каталог GAC - это один из видов регистрации сборки в системе, хотя это никак не затрагивает реестр Windows. Установка сборок в GAC делает невозможным простые установку, копирование, восстановление, перенос и удаление приложения. По этой причине рекомендуется избегать глобального развертывания и использовать закрытое развертывание сборок всюду, где это только возможно.

Зачем «регистрировать» сборку в каталоге GAC? Представьте себе, что две компании сделали каждая свою сборку Calculus, состоящую из единственного файла: Calculus.dll. Очевидно, эти файлы нельзя записывать в один каталог, поскольку файл, копируемый последним, перезапишет первый и тем самым нарушит работу какого-нибудь приложения. Если для установки в GAC использовать специальный инструмент, он создаст в каталоге C:\Wiпdows\Assembly отдельные папки для каждой из этих сборок и скопирует каждую сборку в свою папку.

Обычно пользователи не просматривают структуру каталогов GAC, поэтому для вас она не имеет реального значения. Довольно того, что структура ката­ логов GAC известна CLR и инструментам, работающим с GAC.

Компоновка сборки, ссылающейся на сборку со строгим именем

Какую бы сборку вы ни компоновали, в результате всегда получается сборка, ссылающаяся на другую сборку со строгим именем. Это утверждение верно хотя бы потому, что класс System.Object определен в MSCorLib.dll, сборке со строгим именем. Однако велика вероятность того, что сборка также будет ссылаться на типы из других сборок со строгими именами, изданными Microsoft, сторонними разработчиками либо созданными в вашей организации. В главе 2 показано, как использовать компилятор CSC.exe с параметром /reference для определения сборки, на которую должна ссылаться компонуемая сборка. Если вместе с именем файла задать полный путь к нему, CSC.exe загрузит указанный файл и использует его метаданные для компоновки сборки. Как отмечено в главе 2, если задано имя файла без указания пути, CSC.exe пытается найти нужную сборку в следующих каталогах (просматривая их в том порядке, в ка­ ком они здесь приводятся).

1. Рабочий каталог.
2. Каталог, где находится файл CSC.exe. Этот каталог также содержит DLL­ библиотеки CLR.
3. Каталоги, заданные параметром командной строки /lib при вызове CSC.ехе.
4. Каталоги, указанные в переменной окружения LIВ.

Таким образом, чтобы скомпоновать сборку, ссылающуюся на файл System.Drawing.dll разработки Microsoft, при вызове CSC.exe можно задать параметр /reference: System.Drawing.dll. Компилятор проверит перечисленные каталоги и обнаружит файл System.Drawing.dll в одном каталоге с файлом среды CLR, которую сам использует для создания сборки. Однако несмотря на то, что при компиляции сборка находится в этом каталоге, во время выполнения эта сборка загружается из другого каталога.

Во время установки .NET Framework все файлы сборок, созданных Microsoft, устанавливаются в двух экземплярах. Один набор файлов заносится в один каталог с CLR, а другой -в каталог GAC. Файлы в каталоге CLR облегчают компоновку пользовательских сборок, а их копии в GAC предназначены для загрузки во время выполнения.

Утилита CSC.exe не ищет нужные для компоновки сборки в GAC, чтобы вам не пришлось задавать громоздкие пути к файлам сборки. CSC.exe также позволяет задавать сборки при помощи не менее длинной, но чуть более изящной строки вида:

{codecitation class="brush: plain; gutter: true;" width="100%" }System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken= b03f5f7flld50a3a{/codecitation}

Оба способа столь неуклюжи, что было решено предпочесть им установку на пользовательский жесткий диск двух копий файлов сборок.

Примечание. При компоновке сборки иногда требуется сослаться на другую сборку, существующую в двух версиях - х86 и х64. К счастью, подкаталоги каталога GAC могут хранить версии х86 и х64 одной сборки. Но, поскольку у этих сборок одно имя, их нельзя разместить в одном каталоге с CLR. Но это и неважно, при установке .NET Framework версии х86, х64 или IA64 сборок устанавливаются в каталоге CLR. При компоновке сборки можно ссылаться на любую версию ранее установленных файлов, так как все версии содержат одинаковые метаданные и различаются только кодом. Во время выполнения нужная версия сборки будет загружена из подкаталога GAC_32 или GACJ54. Далее в этой главе показано, как во время выполнения CLR определяет, откуда загружать сборку.

Устойчивость сборок со строгими именами к несанкционированной модификации

Подписание файла закрытым ключом гарантирует, что именно держатель соответствующего открытого ключа является производителем сборки. При установке сборки в GAC система рассчитывает хэш содержимого файла с манифестом и сравнивает полученное значение с цифровой подписью RSA, встроенной в РЕ-файл (после извлечения подписи с помощью открытого ключа). Идентичность значений означает, что содержимое файла не было модифицировано, а также то, что открытый ключ подписи соответствует закрытому ключу издателя. Кроме того, система рассчитывает хэш содержимого других файлов сборки и сравнивает полученные значения с таковыми из таблицы манифеста FileDef. Если хоть одно из значений не совпадает, значит, хотя бы один из файлов сборки был модифицирован и установка сборки в каталог GAC окончится неудачей.

Примечание. Этот механизм гарантирует лишь неприкосновенность содержимого файла; подлинность издателя он гарантирует, только если вы совершенно уверены, что обладаете открытым ключом, созданным издателем, и закрытый ключ издателя не был скомпрометирован. Если издатель желает связать со сборкой свои идентификационные данные, он должен дополнительно воспользоваться технологией Microsoft Authenticode.

Когда приложению требуется привязка к сборке, на которую оно ссылается, CLR использует для поиска этой сборки в GAC ее свойства (имя, версию, региональные стандарты и открытый ключ). Если нужная сборка обнаруживается, возвращается путь к каталогу, в котором она находится, и загружается файл с ее манифестом. Такой механизм поиска сборок гарантирует вызывающей стороне, что во время выполнения будет загружена сборка издателя, создавшего ту сборку, с которой компилировалась программа. Такая гарантия возможна благодаря соответствию маркера открытого ключа, хранящегося в таблице AssemblyRef ссылающейся сборки, открытому ключу из таблицы AssemblyDef сборки, на которую ссылаются. Если вызываемой сборки нет в GAC, CLR сначала ищет ее в базовом каталоге приложения, затем проверяет все закрытые пути, указанные в конфигурационном файле приложения, потом, если приложение установлено при помощи MSI, CLR просит MSI найти нужную сборку. Если ни в одном из этих вариантов сборка не находится, привязка заканчивается неудачей и генерируется исключение System.IO.FileNotFoundException.

Примечание. Когда сборка со строгим именем загружается из каталога GAC, система гарантирует, что файлы, содержащие манифест, устойчивы к несанкционированной модификации. Эта проверка происходит только один раз на этапе установки. Для улучшения производительности среда CLR не проверяет, были ли файлы несанкционированно модифицированы, и загружает их в домен приложений с полными правами. В то же время, когда сборка со строгим именем загружается не из каталога GAC, среда CLR проверяет файл манифеста сборки дабы удостовериться в том, что он устойчив к несанкционированной модификации, занимая дополнительное время для проверки каждый раз во время загрузки этого файла.

При загрузке сборки со строгим именем не из GAC, а из другого каталога (каталога приложения или каталога, заданного значением элемента codeBase в конфигурационном файле) CLR проверяет ее хэш. Иначе говоря, в данном случае расчет хэша для файла выполняется при каждом запуске приложения. Хотя при этом несколько снижается быстродействие, без таких мер нельзя гарантировать, что содержимое сборки не подверглось несанкционированной модификации. Обнаружив во ' время выполнения несоответствие значений хэша, CLR генерирует исключение System.IО.FileLoadException.

Отложенное подписание

Ранее в этой главе обсуждался способ получения криптографической пары ключей при помощи утилиты SN.exe. Эта утилита генерирует ключи, вызывая функции предоставленного Microsoft криптографического АРI-интерфейса под названием CryptoAPI. Полученные в результате ключи могут сохраняться в файлах на любых запоминающих устройствах. Например, в крупных организациях (вроде Microsoft) генерируемые закрытые ключи хранятся на аппаратных устройствах в сейфах, и лишь несколько человек из штата компании имеют доступ к закрытым ключам. Эти меры предосторожности предотвращают компрометацию закрытого ключа и обеспечивают его целостность. Ну, а открытый ключ, естественно, общедоступен и распространяется свободно.

Подготовившись к компоновке сборки со строгим именем, надо подписать ее закрытым ключом. Однако при разработке и тестировании сборки очень неудобно то и дело доставать закрытый ключ, который хранится «за семью печатями», поэтому .NET Framework поддерживает отложенное (delayed signing), или частичное (partial signing), подписание. Отложенное подписание позволяет компоновать сборку с открытым ключом компании, не требуя закрытого ключа. Открытый ключ дает возможность встраивать в записи таблицы AssemblyRef сборки, ссылающиеся на вашу сборку, получать правильное значение открытого ключа, а также корректно размещать эти сборки во внутренней структуре GAC. Не подписывая файл закрытым ключом, вы полностью лишаетесь защиты от несанкционированной модификации, так как при этом не рассчитывается хэш сборки и цифровая подпись не включается в файл. Однако на данном этапе это не проблема, поскольку подписание сборки откладывается лишь на время ее разработки, а готовая к упаковке и развертыванию сборка подписывается закрытым ключом.

Обычно открытый ключ компании получают в виде файла и передают его утилитам, компонующим сборку. (Как уже отмечалось в этой главе, чтобы извлечь открытый ключ из файла, содержащего пару ключей, можно вызвать утилиту SN.exe с параметром -р.) Следует также указать компонующей про­ грамме сборку, подписание которой будет отложено, то есть ту, что будет скомпонована без закрытого ключа. В компиляторе С# для этого служит параметр /delaysign. В Visual Studio в окне свойств проекта нужно перейти на вкладку Sigпiпg и установить флажок Delay sigп опlу. При использовании утилиты AL.exe необходимо задать параметр /delay[sign].

Обнаружив, что подписание сборки откладывается, компилятор или утилита AL.exe генерирует в таблице метаданных сборки AssemblyDef запись с открытым ключом сборки. Как обычно, наличие открытого ключа позволяет разместить эту сборку в GAC, а также создавать другие сборки, ссылающиеся на нее, при этом у них в записях таблицы метаданных AssembyRef будет верное значение от­ крытого ключа. При компоновке сборки в результирующем РЕ-файле остается место для цифровой подписи RSA. (Компонующая утилита определяет размер необходимого свободного места, исходя из размера открытого ключа.) Кстати, и на этот раз хэш файла не рассчитывается.

На этом этапе результирующая сборка не имеет действительной цифровой под­ писи. Попытка установки такой сборки в GAC окончится неудачей, так как хэш содержимого файла не был рассчитан, что создает видимость повреждения файла. Для того чтобы установить такую сборку в GAC, нужно запретить системе проверку целостности файлов сборки, вызвав утилиту SN.exe с параметром командной строки -Vr. Вызов SN.exe с таким параметром также вынуждает CLR пропустить проверку значения хэша для всех файлов сборки при ее загрузке во время выполнения. С точки зрения внутренних механизмов системы, параметр -Vr утилиты SN.exe обеспечивает размещение идентификационной информации сборки в раз­ деле реестра HKEY_LOCAL_ MACHINE\SOFТWARE\Microsoft\StrongName\Verification.

Примечание. При использовании любой утилиты, имеющей доступ к реестру, необходимо убедиться в том, что для 64-разрядной платформы используется соответствующая 64-разрядная утилита. По умолчанию утилита под 32-разрядную платформу х86 установлена в каталоге C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\bin\NETFX 4.0 Tools, а утилита под 64-разрядную платформу х64-в каталоге C:\Program Files (x86)\Microsoft SDKs\Windows\ v7.0A\bin\NETFX 4.0 Tools\x64.

Окончательно протестированную сборку надо официально подписать, чтобы сделать возможными ее упаковку и развертывание. Чтобы подписать сборку, снова вызовите утилиту SN.exe, но на этот раз с параметром -R, указав имя файла, содержащего настоящий закрытый ключ. Параметр -R заставляет SN.exe рассчитать хэш содержимого файла, подписать его закрытым ключом и встроить цифровую подпись RSA в зарезервированное свободное место. После этого подписанная по всем правилам сборка готова к развертыванию. Можно также отменить проверку сборки, вызвав SN.exe с параметром -Vu или -Vx.

Полная последовательность действий по созданию сборки с отложенным подписанием выглядит следующим образом.

1.Во время разработки сборки следует получить файл, содержащий лишь от­ крытый ключ компании, и добавить в строку компиляции сборки параметры /keyfileи /delaysign:

{codecitation class="brush: plain; gutter: true;" width="100%" }csc /keyfile:MyCompany.PublicKey /delaysign MyAssembly.cs{/codecitation}

2.После компоновки сборки надо выполнить показанную далее команду, чтобы получить возможность тестирования этой сборки, установки ее в каталог GAC и компоновки других сборок, ссылающихся на нее. Эту команду до­ статочно исполнить лишь раз, не нужно делать это при каждой компоновке сборки.

{codecitation class="brush: plain; gutter: true;" width="100%" }SN.exe -Vr MyAssembly.dll{/codecitation}

3.Подготовившись к упаковке и развертыванию сборки, надо получить за­ крытый ключ компании и выполнить приведённую далее команду. При желании можно установить новую версию GAC, но не пытайтесь это сделать до выполнения шага 4.

{codecitation class="brush: plain; gutter: true;" width="100%" }SN.exe -R MyAssembly.dll MyCompany.PrivateKey{/codecitation}

4.Для тестирования сборки в реальных условиях, чтобы снова включить проверку, выполните следующую команду:

{codecitation class="brush: plain; gutter: true;" width="100%" }SN -Vu MyAssembly.dll{/codecitation}

В начале раздела говорилось о хранении ключей организации на аппаратных носителях, например на смарт-картах. Для того чтобы обеспечить безопасность ключей, необходимо следить, чтобы они никогда не записывались на диск в виде файлов. Криптографические провайдеры (Cryptographic Service Providers, CSP) операционной системы предоставляют контейнеры, позволяющие абстрагироваться от физического места хранения ключей. Например, Microsoft использует СSР-провайдер, который при обращении к контейнеру считывает закрытый ключ со смарт-карты.

Если пара ключей хранится в СSР-контейнере, необходимо использовать другие параметры при обращении к утилитам CSC.exe, AL.exe и SN.exe. При компиляции (CSC.exe) вместо /keyfilе нужно задействовать параметр /keycontainer, при компоновке (AL.exe) - параметр /keyname вместо /keyfilе, а при вызове SN.exe для добавления закрытого ключа к сборке, подписание которой было отложено, - параметр -Re вместо -R. SN.exe поддерживает дополнительные параметры для работы с CSP.

Примечание. Откладывать подписание удобно, когда необходимо выполнить какие-либо действия над сборкой до ее развертывания. Например, может понадобиться применить к сборке защитные утилиты, модифицирующие до неузнаваемости код. После подписания сборки это сделать уже не удастся, так как хэш станет недействительным. Так что если после компоновки сборки нужно ее защитить от декомпиляции или выполнить над ней другие действия, надо применить методику отложенного подписания. В конце нужно запустить утилиту SN.exe с параметром -R или -Re, чтобы завершить подписание сборки и рассчитать все необходимые хэш-значения.

Прочитано 16310 раз

Похожие материалы (по тегу)

   

Поиск  

   

Материалы