заданных для клиента и сервера). Уровень имперсонализации используется в тех случаях, когда какой-либо поток данного
приложения будет вызывать другое серверное приложение, выступая в роли клиента.
z Идентификационные данные
Исполняемое серверное приложение выступает в роли принципала со своими именем, паролем, SID. Ранее (в COM)
серверное приложение могло запускаться под идентификацонными данными запустившего его клиента, но такое решение
было признано немасштабируемым. В COM+ администратор выбирает один из двух вариантов:
{ Интерактивный пользователь
В этом случае запускаемое серверное приложение будет исполняться под идентификационными данными (и с
правами) пользователя, имеющего в данный момент интерактивный сеанс на машине, где установлено серверное
приложение. Это имеет свои плюсы и минусы. Удобен этот режим для отладки, для интерактивных приложений.
Однако для неинтерактивных приложений этот способ опасен. Во
-первых, серверное приложение может получить
права администратора, если администратор в данный момент вошел в систему. Во-вторых, при выходе
интерактивного пользователя из системы, серверное приложение, запущенное под идентификационными данными
данного пользователя, будет также завершено.
{ Заданный пользователь
В этом случае администратор задает для конкретного серверного приложения уникальные имя и пароль, регистрируя
приложение как нового пользователя в системе с определенными правами. Передача прав клиента серверному
приложению возможна через механизм имперсонализации.
z Роли
В COM+ механизм ролей используется при авторизации клиентов. Авторизация клиента означает выяснение его прав,
связанных с запуском серверного приложения, с вызовом того или иного метода серверного объекта. При
конфигурировании серверного приложения администратор определяет список ролей, которым могут принадлежать
клиенты. Далее к каждой роли приписываются те или иные пользователи, зарегистрированные в домене
. Удобно
приписывать к одной роли целую группу пользователей (с заданным SID). Одной роли можно приписать многих
пользователей, и один пользователь может исполнять несколько ролей. Классические примеры ролей: клерк, менеджер.
После распределения пользователей по ролям (относительно данного серверного приложения), администратор может
приписать определенные роли приложению в целом, отдельным его компонентам, интерфейсам и
методам. В результате,
доступ к некоторому ресурсу (компоненту, интерфейсу, методу) получают только те клиенты, которые выполняются с SID
пользователя, исполняющего соответствующую роль.
Приписывание роли некоторому ресурсу означает, что эта же роль приписывается и всем ресурсам, входящим в данный
ресурс. Например, приписывание некоторой роли всему приложению означает, что всем его компонентам, их интерфейсам
и методам приписана эта же роль. Это ограничивает возможность более тонкого контроля доступа (программируемого
контроля) к компонентам приложения. Следует приписывать роли отдельным компонетам, интерфейсам и методам. В этом
случае разнообразная связанная с безопасностью информация будет включена в контекст соответствующих объектов, что
позволит выполнять программный контроль за доступом.
В связи с
рассмотренным только что вопросом о ролях уместно более подробно остановиться на программируемом контроле
доступа к приложению. Механизм ролей позволяет разрешить или запретить вызов некоторого метода некоторого серверного
объекта всем клиентам, исполняющим определенную роль. Однако, в некоторых случаях желательно иметь более тонкий
контроль на доступом, учитывающий не только роль клиента, но и
значения параметров, которые этот клиент задал при вызове
метода. В этом случае не обойтись без программируемого контроля на стороне сервера.
С каждым вызовом некоторого метода серверного объекта связан так называемый контекст безопасности вызова (конечно, для
этого должны быть заданы роли, и некоторая роль должна быть приписана этому методу или содержащему
его интерфейсу,
компоненту, но не всему приложению). Имеется интерфейс
ISecurityCallContext, через который можно получить доступ к
этому контексту. Для получения указателя на этот интерфейс можно вызвать из потока, исполняющего данный метод, функцию
CoGetCallContext. В качестве входного параметра задается идентификатор запрашиваемого интерфейса
(
IID_ISecurityCallContext), через выходной параметр возвращается указатель на этот интерфейс.
Для нашей задачи контроля доступа к методу в зависимости от параметров можно использовать следующие методы данного
интерфейса:
z IsSecurity Enabled возвращает как выходной параметр логическое значение: TRUE, если основанная на ролях система
безопасности задействована, и
FALSE в противном случае.
z Если система безопасности задействована, то метод IsCallerInRole используется для проверки принадлежности клиента,
вызвавшего метод, заданной роли. Входной параметр задает строку с ролью, выходной возвращает истину или ложь в
зависимости от принадлежности клиента специфицированной роли. В зависимости от этого значения можно продолжить
выполнение основной логики метода, либо прервать его выполнение с соответствующим кодом ошибки.
Вообще, интерфейс
ISecurityCallContext позволяет получить следующую информацию об исполняемом вызове:
z Длина цепи вызовов
Как уже отмечалось ранее, в COM каждый вызов получает уникальный идентификатор, и все последующие вызовы,
сделанные ради выполнения данного вызова, получают тот же идентификатор. Это позволяет отслеживать цепочки
вызовов.
z Минимальный уровень аутентификации, использующийся в данной цепи вызовов
z Идентификационная информация для всех клиентов, сделавших включенные в данную цепь вызовы:
{ SID
{ Имя
{ Сервис аутентификации (например, Kerberos)
{ Уровни аутентификации и имперсонализации
z Идентификационные данные клиента, сделавшего первый вызов в цепи
z Идентификационные данные клиента, сделавшего последний вызов в цепи
Теперь рассмотрим, как на стороне сервера решается вопрос имперсонализации клиента и делегирование его прав при удаленном