Платформа Geneva

Создание собственной службы маркеров безопасности

Мишель Леру Бустамант (Michele Leroux Bustamante)

Эта статья основана на предварительной версии платформы Geneva. В любую содержащуюся в ней информацию могут быть внесены изменения.

В данной статье рассматриваются следующие вопросы.
  • Реализация службы маркеров безопасности с помощью платформы Geneva
  • Интегрированная безопасность
  • Преобразование заявок
В данной статье используются следующие технологии.
Windows Communication Foundation, ASP.NET, платформа Geneva Framework

Загружаемый файл с кодом доступен в коллекции кода MSDN
Обзор кода в интерактивном режиме

Cодержание

Знакомство со службами маркеров безопасности
Создание собственной активной службы маркеров безопасности
Расширение SecurityTokenService
Размещение и настройка службы маркеров безопасности
Обработчики маркеров безопасности
Создание собственной пассивной службы маркеров безопасности
Элемент управления FederatedPassiveTokenService
SessionAuthenticationModule
Проверка подлинности пользователя
Преобразование заявок
Заключение

Платформенная стратегия доступа на основе заявок Майкрософт (CBA) – под кодовым названием «Geneva» – включает в себя платформу «Geneva» Framework, «Geneva» Server и Windows CardSpace «Geneva». Платформа Geneva предоставляет разработчикам средства по созданию приложений и служб на основе заявок, включающие в себя маркеры, выпущенные службой маркеров безопасности (STS), а также средства для создания собственной STS и приложений с поддержкой Windows CardSpace. Geneva Server – это корпоративная STS, тогда как платформа Geneva делает возможным создание собственных STS для сред, не требующих функций корпоративного уровня. Windows CardSpace Geneva – это эволюция Windows CardSpace как средства выбора и поставки удостоверений на клиентских компьютерах Windows.

В свой последней статье о платформе Geneva я рассказал о более эффективном способе создания служб Windows Communication Foundation (WCF) на основе заявок, которые полагаются на маркеры, выпущенные STS. Здесь я создам мою собственную STS с помощью Geneva Framework.

Прежде чем продолжать чтение, стоит прочитать технический документ для разработчиков по платформе Geneva, написанный Кейтом Брауном (Keith Brown) и Сеша Мани (Sesha Mani), а также мою последнюю статью, «Geneva Framework: Лучший подход к созданию служб WCF на основе заявок».

Знакомство со службами маркеров безопасности

Основана ли STS на Geneva Server или создана с помощью Geneva Framework, ее основной ролью является работа в качестве шлюза безопасности для проверки подлинности вызывающих и выдачи маркеров безопасности, несущих заявки, которые описывают вызывающего. Читатели могут вспомнить, по вышеупомянутым статьям, что существует несколько сценариев, поддерживаемых проверкой подлинности STS:

  • Отделение приложений и служб от механизма проверки подлинности, чтобы они могли сконцентрироваться на авторизации относящихся к ним заявок.
  • Поддержка нескольких типов учетных данных без усложнения реализации приложений и служб.
  • Поддержка интегрированных сценариев, где подлинность пользователей проверяется их доменом и им дается доступ к ресурсам в другом домене – путем установки отношений доверия между STS каждого домена.
  • Облегчение сценариев делегирования идентификации, где проверенному пользователю дается доступ к подчиненным службам.
  • Облегчение преобразования заявок, чтобы нужные заявки были доступны для авторизации на приложениях и службах.

Любой из этих сценариев может базироваться на пассивной интеграции (на основе обозревателя) или активной интеграции (на основе клиента Windows). Далее я расскажу подробнее об этих сценариях, когда буду описывать, как встроить относящуюся к ним логику в собственную STS, созданную с помощью Geneva Framework.

Прежде чем углубляться в реализацию STS, давайте сперва вспомним про некоторые основы. STS, используемая в активной интеграции – это реализация WS-Federation Active Requestor Profile (см. технический комитет WS-Federation) и (в первую очередь) спецификации WS-Trust (см. WS-Trust 1.3).

Если говорить в целом, WS-Trust описывает контракт с четырьмя операциями служб: Issue, Validate, Renew и Cancel («Выдать», «Проверить», «Обновить» и «Отменить»). Эти операции вызываются клиентами, чтобы запросить маркер безопасности, проверить его, обновить истекший маркер или отменить маркер безопасности, которые более не следует использовать, соответственно. Каждой операции отправляются сообщения в форме запроса маркера безопасности (RST), на которые она реагирует в форме ответа на этот запрос (RSTR), соответственно спецификации WS-Trust. Для этой статьи я буду предполагать, что выданный маркер является маркером языка SAML 1.1 или SAML 2.0.

Рис. 1 иллюстрирует основное содержимое RST и RSTR для активного экземпляра маркера. Сообщение RST включает необходимую информацию для запроса маркера безопасности, включая тип маркера, который следует выдать (в нашем случае SAML), заявки, включение которых в выданный маркер запрашивается доверяющей стороной (RP), информация о RP (AppliesTo), включая URL-адрес, как правило, обычно сертификат, определяющий RP и, необязательно (не показывается), ключевой материал для использования в ключе проверки владения (ключе проверки), возвращаемом с RSTR.

fig01.gif

Рис. 1. Выдача маркеров для сценария активной интеграции

Если выдача маркера успешна, RSTR будет включать в себя выданный маркер SAML и ключ проверки (предполагая, что STS решит, какой ключ проверки использовать и в силу этого должна будет возвратить его в RSTR). Маркер SAML будет включать относящиеся к делу заявки от проверенной стороны, подписывается STS для защиты маркера от несанкционированных изменений, содержит ключ проверки, зашифрованный для RP и сам шифруется для RP, так что лишь предполагаемый получатель может обработать его.

Клиент использует ключ проверки, чтобы подписать сообщение к RP. RP должен иметь возможность расшифровать ключ проверки внутри маркера SAML или отвергнуть сообщение. Если ключ проверки внутри маркера совпадает с подписью сообщения, это доказывает, что вызов к RP был отправлен стороной, запросившей маркер.

Пассивные сценарии интеграции основаны на WS-Federation Passive Requestor Profile, который включает связь на основе обозревателя. Лежащий в основе обмен сообщениями все еще основан на WS-Trust; однако RST разбит на параметры строки запроса по URL-адресу STS, и RSTR обычно передается RP как параметр формы. Пассивная STS и RP перехватывают эти параметры с помощью веб-обработчиков интеграции. Пассивная STS может обрабатывать запросы WS-Trust напрямую или передавать их лежащей в основе реализации WS-Trust. Рис. 2 иллюстрирует, как RST и RSTR обрабатываются в сценарии пассивной интеграции.

fig02.gif

Рис. 2. Выдача маркеров для сценария пассивной интеграции

Одним существенным различием между сценариями активной и пассивной интеграции является тип выдаваемого маркера SAML. Активная интеграция обычно полагается на маркер SAML, использующий подтверждение субъекта типа «держатель ключа», а это значит, что ключ проверки используется как я описал выше, чтобы подтвердить, что клиент, отправляющий маркер для проверки, является субъектом, запросившим маркер (это также известно как поведение ActAs). Сценарии пассивной интеграции обычно включают в себя маркер SAML с подтверждением субъекта типа «носитель» (он также известен как маркер-носитель). Этот тип маркера не включает ключа проверки и порой именуется бесключевым маркером. Он полагается на передачу данных для безопасного получения ключа от STS и передачи его RP.

Эти концепции (WS-Federation, WS-Trust и маркеры SAML) являются важной справочной информацией для следующей дискуссии. Сперва я опишу, как создать активную STS, используя платформу Geneva. Затем я расскажу о создании пассивной STS и, наконец, представлю некоторые расширенные сценарии для обеих случаев.

Создание собственной активной службы маркеров безопасности

В простом сценарии активной интеграции, подобном показанному на рис. 3, обычно присутствуют следующие ниже участники.

  • RP – это служба, вызванная клиентом.
  • Единственная STS, также реализованная как служба, поддерживающая протокол WS-Trust. Эта STS проверяет подлинность вызывающих и выдает маркер безопасности с заявками, определяющий вызывающего, также известный как поставщик идентификаторов (Identity Provider) или IP-STS.
  • Клиент, в данном случае приложение на основе Windows, полагающееся на прокси для удостоверения своей подлинности STS, чтобы получить выпущенный маркер и отправить сообщения RP, предоставляющий выпущенный маркер для проверки подлинности и авторизации.

fig03a.gif

Рис. 3. Простой сценарий интеграции с единственной доверяющей стороной (RP) и активным IP-STS

Рис. 4 иллюстрирует движущиеся части в основе этой реализации. В него включена специальная реализация SecurityTokenService, использование расширения ServiceHost (WSTrustServiceHost) с целью инициализации среды для интеграции, настройка одной или нескольких конечных точек WS-Trust с помощью производного WSTrustContract и другие параметры конфигурации, относящиеся к среде выполнения модели идентификации. В следующих разделах я рассмотрю каждый из этих элементов реализации пользовательской STS, основанной на платформе Geneva.

fig04.gif

Рис. 4. Архитектура реализации для пользовательской активной STS и активным IP-STS

Расширение SecurityTokenService

Платформа Geneva предоставляет основные функции для создания собственной STS через тип SecurityTokenService из пространства имен Microsoft.IdentityModel.SecurityTokenService. Этот абстрактный класс выполняет всю тяжелую работу по обработке сообщений RST и RSTR и созданию маркеров безопасности. Специально созданная STS наследует этот класс и предоставляет (как минимум) следующие ниже компоненты.

  • Конструктор, принимающий пользовательский экземпляр SecurityTokenServiceConfiguration для настройки некоторых базовых функций STS (об этом будет рассказано позже).
  • Переопределение для GetScope, для проверки целевой RP запроса и предоставления адекватных учетных данных шифрования для этой RP и учетных данных подписи для маркера безопасности.
  • Переопределение GetOutputClaimsIdentity, предоставляющее заявки получившемуся маркеру безопасности.

Рис. 5показывает часть кода для реализации простой пользовательской STS с этими функциями. Вспомним про поток взаимодействий для активной STS с рис. 1 и 2. Реализация STS, IdentitySTS, проверяет входящий RST при вызове GetScope – удостоверяясь в том, что элемент AppliesTo от RST действительно указывает на доверенный URI. Предположительно, STS управляет списком доверенных RP, для которых могут быть выпущены маркеры, вместе с их сертификатами. GetScope получает свойство EncryptingCredentials области соответствующему сертификату, если AppliesTo проходит проверку, в данном случае "RPKey". Кроме того, свойство SigningCredentials установлено на использование соответствующего сертификата для подписи доверенного маркера. Обычно это частный ключ STS, в данном случае "IPKey".

Рис. 5. Простая реализация пользовательской STS

public class IdentitySTS : SecurityTokenService
{
    public IdentitySTS(SecurityTokenServiceConfiguration config)
        : base( config )
    {
    }

    protected override IClaimsIdentity GetOutputClaimsIdentity(
        IClaimsPrincipal principal, RequestSecurityToken request, 
        Scope scope)
    {
        IClaimsIdentity claimsIdentity = new ClaimsIdentity();

        claimsIdentity.Claims.Add(new Claim(ClaimTypes.Name, 
            principal.Identity.Name));
        claimsIdentity.Claims.Add(new Claim(ClaimTypes.Role, "Users"));

        return claimsIdentity;
    }

    protected override Scope  GetScope(
        Microsoft.IdentityModel.Claims.IClaimsPrincipal principal, 
        RequestSecurityToken request)
    {

        Scope scope = new Scope(request);
        scope.EncryptingCredentials = this.GetCredentialsForAppliesTo(
                                                     request.AppliesTo);
        scope.SigningCredentials = new 
          X509SigningCredentials(CertificateUtil.GetCertificate(StoreName.My, 
          StoreLocation.LocalMachine, "CN=IPKey"));
        return scope;
    }

    private X509EncryptingCredentials GetCredentialsForAppliesTo(Endpoint
        Address appliesTo)
    {
        if (appliesTo == null || appliesTo.Uri ==null || 
          string.IsNullOrEmpty(appliesTo.Uri.AbsolutePath))
        {
            throw new InvalidRequestException(
                "AppliesTo must be supplied in the RST.");
        }

        X509EncryptingCredentials creds = null;
        if (appliesTo.Uri.AbsoluteUri.StartsWith(
            "http://localhost:8000/RelyingPartyService"))
        {
            creds = new X509EncryptingCredentials(
                CertificateUtil.GetCertificate(StoreName.TrustedPeople, 
                StoreLocation.LocalMachine, 
                "CN=RPKey"));
        }
        else
            throw new InvalidRequestException(String.Format(
                "Invalid relying party address: {0}", 
                appliesTo.Uri.AbsoluteUri));

        return creds;
    }
}

Когда вызывается GetOutputClaimsIdentity, ClaimsPrincipal передается средой выполнения вместе с идентификатором проверенного пользователя. Этот идентификатор обычно используется, чтобы определить заявки, которые следует дать вызывающему. На рис. 5 код создает заявку имени и жестко закодированную заявку роли для вызывающего и возвращает это в форме ClaimsIdentity. Эта ClaimsIdentity поставляет заявки среде выполнения для маркера, который предстоит выпустить.

Эту реализацию STS также можно расширить с помощью следующих функций.

  • GetOutputClaimsIdentity может включать код для поиска пользователя в нестандартном хранилище учетных данных и поиска дополнительных заявок. Например, список ролей, другие важные сведения о пользователе, такие как адрес электронной почты или пользовательские заявки, представляющие более детализированные права приложения, например создание, чтение, обновление или удаление.
  • GetScope может искать URI-адрес AppliesTo в пользовательской базе данных, перечисляющей все доверенные RP и связанные с ними сертификаты.

Размещение и настройка службы маркеров безопасности

Те, кто знаком с WCF, знают, что для отправки клиентами сообщений службе необходимо настроить одну или несколько конечных точек. В случае STS контракт службы, который предстоит использовать в каждой конечной точке, должен быть основан на протоколе WS-Trust, который включает в себя четыре операции: Issue, Validate, Renew и Cancel («Выдать», «Проверить», «Обновить» и «Отменить»). Фактически существуют две версии протокола WS-Trust, которые могут быть применены STS:

  • WS-Trust 1.3: последняя версия спецификаций WS-Trust.
  • WS-Trust от февраля 2005 г.: версия WS-Trust, примененная многими партнерами по отрасли, пока они ожидали ратификации стандарта.

Также можно предоставить асинхронные реализации для GetScope(), GetOutputClaimsIdentity() – в числе других методов – в типе SecurityTokenService. Это улучшает масштабируемость операций с интенсивным вводом-выводом, таких как доступ к сертификатам или взаимодействие с данными заявок. При настройке конечных точек для STS необходимо выбрать, какой контракт предоставить для конечной точки. Пространство имен Microsoft.IdentityModel.Protocols включает в себя два контракта служб для конечных точек STS: IWSTrust13SyncContract и IWSTrustFeb2005SyncContract. Рис. 6 показывает конфигурацию для службы STS с двумя конечными точками, одной для каждого контракта. Следует отметить, что существуют также асинхронные версии контракта, которые будут использоваться для применения асинхронного прокси: IWSTrust13AsyncContract и IWSTrustFeb2005AsyncContract.

Рис. 6. Конфигурация службы STS с несколькими конечными точками WS-Trust

<service name=
  "Microsoft.IdentityModel.Protocols.WSTrust.WSTrustServiceContract" 
  behaviorConfiguration="stsBehavior">
  <endpoint address="WSTrustFeb05" binding="wsHttpBinding" 
    contract="Microsoft.IdentityModel.Protocols.WSTrust.
    IWSTrustFeb2005SyncContract"/>
  <endpoint address="WSTrust13" binding="wsHttpBinding"  
    contract="Microsoft.IdentityModel.Protocols.WSTrust.
    IWSTrust13SyncContract"/>
</service>

STS должна предоставить конечную точку, основанную на версии WS-Trust от февраля 2005 г., для обратной совместимости с существующими клиентами. Типом службы, применяющим оба контракта, является тип WSTrustServiceContract, который можно найти в пространстве имен Microsoft.IdentityModel.Protocols.WSTrust. Это тип, на который следует ссылаться в разделе конфигурации <service> для STS.

Как показано на схеме на рис. 4, конфигурация <service> и ее конечные точки используются для инициализации носителя с помощью верного типа WSTrustServiceContract. Этот тип также инициализируется с помощью ссылки на пользовательскую реализацию SecurityTokenService в ходе инициализации носителя. Так среда выполнения направляет сообщения к пользовательской STS.

На рис. 6 обе конечные точки STS полагаются на учетные данные Windows для проверки подлинности вызывающих (поведение wsHttpBinding по умолчанию). STS может предоставить несколько конечных точек с варьирующимися координатами привязки для поддержки различных типов учетных данных. Это также включает в себя настройку соответствующего обработчика маркеров безопасности для каждого типа учетных данных. О конфигурации обработчиков маркеров я поговорю чуть ниже.

Платформа Geneva поддерживает модифицируемый тип ServiceHost, WSTrustServiceHost, для использования при размещении экземпляров STS. Нижеследующий код иллюстрирует конструирование типа WSTrustServiceHost в саморазмещающей среде:

WSTrustServiceHost stsHost = 
  new WSTrustServiceHost(new IdentitySTSConfiguration());
stsHost.Open();

WSTrustServiceHost полагается на пользовательский экземпляр SecurityTokenServiceConfiguration в инициализации среды выполнения с помощью конечных точек WS-Trust, чтобы сделать возможным поведение обмена метаданными для STS и настроить конечную точку обмена метаданными.

При размещении в IIS тип WSTrustServiceHostFactory используется для достижения тех же результатов. В файле SVC конфигурация @ServiceHost указывает тип фабрики и пользовательский тип SecurityTokenServiceConfiguration следующим образом:

<%@ ServiceHost Factory="Microsoft.IdentityModel.Protocols.WSTrust. 
  WSTrustServiceHostFactory" 
  Service="STS.IdentitySTSConfiguration"  %>

Фабрика инициализирует WSTrustServiceHost с указанной конфигурацией после активации.

Пользовательский тип SecurityTokenServiceConfiguration требуется, чтобы инициализировать WSTrustServiceHost для STS. Рис. 7 показывает пользовательскую реализацию, именуемую IdentitySTSConfiguration.

Рис. 7. Пользовательская SecurityTokenServiceConfiguration

public class IdentitySTSConfiguration: SecurityTokenServiceConfiguration
{

    public IdentitySTSConfiguration(): base("http://localhost:8010/sts")
    {

      this.TokenIssuerName = "http://localhost:8010/sts";

      this.SigningCredentials = new 
        X509SigningCredentials(CertificateUtil.GetCertificate(StoreName.My, 
        StoreLocation.LocalMachine, "CN=IPKey"));

      this.SecurityTokenService = typeof( IdentitySTS);

    }

}

Этот тип должен предоставить URI-адрес для STS, учетные данные подписи и ссылку на тип STS, с которым связана конфигурация. URL-адрес должен быть допустимым в случае выпуска STS управляемых карт – чтобы Windows CardSpace могло импортировать эти карты. Базовый тип требует передачи значения строки конструктору для TokenIssuerName, но я рекомендую переопределить это в коде, чтобы можно было динамически установить URI из конфигурации, вместо жесткого кодирования этого значения, передаваемого конструктору.

Тип SecurityTokenServiceConfiguration также предоставляет свойства, которые можно использовать для установки значений размера ключа и типа маркера по умолчанию, отключения доступа к метаданным, времени жизни маркера и расфазировки синхронизирующих импульсов, установки пользовательских сериализаторов RST и RSTR, настройки обработчиков маркеров, проверяющих подлинность вызывающих и настройки конечных точек WS-Trust.

На следующем примере показано, как отключать доступ к метаданным и как инициализировать конечные точки WS-Trust (подобные показанным на рис. 6) программно, вместо того чтобы полагаться на параметры конфигурации <service>:

IdentitySTSConfiguration config = new IdentitySTSConfiguration();
config.DisableWsdl = true;
config.TrustEndpoints.Add(new 
  ServiceHostEndpointConfiguration("WSTrustFeb05", new WSHttpBinding(),  
  typeof(IWSTrustFeb2005SyncContract)));
config.TrustEndpoints.Add(new ServiceHostEndpointConfiguration(
  "WSTrust13", new WSHttpBinding(), 
  typeof(IWSTrust13SyncContract)));

WSTrustServiceHost stsHost = new WSTrustServiceHost(config);

Базовый тип SecurityTokenServiceConfiguration также читает раздел конфигурации <microsoft.identityModel>, чтобы инициализировать нужные параметры конфигурации STS. Параметры, которые можно декларативно настроить для пользовательской STS, включают максимальную расфазировку синхронизирующих импульсов, обработчики маркеров безопасности для проверки подлинности и выдачи, диспетчер проверки подлинности заявок, реестр имен поставщиков и разрешители маркеров. Рис. 8 показывает несколько полезных параметров, настроенных для STS.

Рис. 8. Конфигурация <microsoft.identityModel> для STS

<microsoft.identityModel>
  <maximumClockSkew value="00:05:00"/>
  <claimsAuthenticationManager type="STS.
    CustomClaimsAuthenticationManager, STS"/>
  <securityTokenHandlers>
    <remove type="Microsoft.IdentityModel.Tokens.
      WindowsUserNameSecurityTokenHandler, 
      Microsoft.IdentityModel, Version=0.5.1.0, Culture=neutral, 
      PublicKeyToken=31bf3856ad364e35" />
    <add type="Microsoft.IdentityModel.Tokens.
      MembershipUserNameSecurityTokenHandler, 
      Microsoft.IdentityModel, Version=0.5.1.0, Culture=neutral, 
      PublicKeyToken=31bf3856ad364e35">
        <usernameSecurityTokenHandlerRequirement 
          membershipProvider="CustomProviders.CustomMembershipProvider, 
          CustomProviders, Version=1.0.0.0, Culture=neutral,
           PublicKeyToken=c03h5a64f15d0b3f" />
    </add>
  </securityTokenHandlers>
</microsoft.identityModel>

Пользовательский тип ClaimsAuthenticationManager вызывается для учетных данных не от Windows, давая возможность предоставить среде выполнения пользовательский тип ClaimsPrincipal, прежде чем выдавать заявки в GetOutputClaimsIdentity. Созданный пользователем маркер безопасности может быть настроен на предоставление параметров, переопределяющих поведение по умолчанию определенного разработчика или изменяющих выбор обработчика маркера безопасности для определенного типа учетных данных.

Обработчики маркеров безопасности

Читатели, вероятно, ожидают определения того, как проверка подлинности и авторизация будут вести себя на каждой конечной точке STS от конфигурации поведения службы. Из моей последней статьи можно вспомнить, что платформа Geneva работает несколько иначе. В случае проверки подлинности коллекция <securityTokenHandlers> указывает типы SecurityTokenHandler, доступные для проверки подлинности входящих запросов.

Эта коллекция может содержать лишь одну запись для каждого типа SecurityTokenHandler. Например, можно зарегистрировать лишь один KerberosSecurityTokenHandler, UserNameSecurityTokenHandler, X509SecurityTokenHandler, Saml11SecurityTokenHandler или Saml2SecurityTokenHandler для обработки запросов соответствующего типа учетных данных. Если конечная точка STS ожидает учетные данные UserNamе, регистрируемым по умолчанию UserNameSecurityTokenHandler является WindowsUserNameSecurityTokenHandler. Рис. 8 иллюстрирует удаление WindowsUserNameSecurityTokenHandler и добавление MembershipUserNameSecurityTokenHandler в качестве его замены – включая связанные параметры конфигурации для поставщика членства.

Можно также создавать пользовательские типы SecurityTokenHandler. Помните, что пока они происходят от соответствующего базового класса, совпадающего с категорией маркеров (например, UserNameSecurityTokenHandler), обработчик по умолчанию можно заменить новым, собственным обработчиков. Рис. 9 иллюстрирует пользовательскую реализацию UserNameSecurityTokenHandler, именуемую CustomUserNameSecurityTokenHandler.

Рис. 9. Пользовательская UserNameSecurityTokenHandler

public class CustomUserNameSecurityTokenHandler:   
  UserNameSecurityTokenHandler
{
  public override ClaimsIdentityCollection ValidateToken(SecurityToken token)
  {
    UserNameSecurityToken userNameToken = token as UserNameSecurityToken;
    AuthenticateUser(userNameToken.UserName, userNameToken.Password);

    return new ClaimsIdentityCollection(new IClaimsIdentity[] {
      new ClaimsIdentity(
        new Claim(System.IdentityModel.Claims.ClaimTypes.Name,
         userNameToken.UserName), "CustomUserNameSecurityTokenHandler")});
  }

  public override bool CanValidateToken
  {
    get { return true; }
  }
}

В пользовательской реализации SecurityTokenHandler должны быть переопределены, как минимум, ValidateToken и CanValidateToken. Внутри ValidateToken пользователь отвечает за проверку подлинности в соответствующем хранилище учетных данных. Результатом этой проверки должен стать набор заявок, которые можно возвратить среде выполнения для присоединения к ClaimsPrincipal от потока запроса.

fig10.gif

Рис. 10. Простой сценарий интеграции с единственной доверяющей стороной (RP) и пассивным IP-STS

Также очень важно переопределить CanValidateToken и вернуть True. Без этого переопределения обработчик маркеров не будет зарегистрирован в коллекции и не будет вызван.

Создание собственной пассивной службы маркеров безопасности

В простом сценарии пассивной интеграции присутствуют те же участники, как показано на рис. 3, что и в сценарии активной интеграции – но клиент теперь является обозревателем, RP – веб-приложением, а IP-STS также рекомендуется веб-приложением для обработки связи на основе HTTP. Рис. 10 иллюстрирует участников и поток сообщений для пассивной интеграции.

Движущиеся части в основе этого сценария подобны показанным на рис. 4, в той мере, в которой это затрагивает основную STS, но в том, как пассивная STS выполняет проверку подлинности и в том, как вызываются лежащие в основе функции STS, существуют очевидные различия. Схема на рис. 10 иллюстрирует эти различия с высокого уровня. Пассивная STS реализуется как веб-узел, требующий шифрования SSL для обеспечения безопасности процесса выдачи маркеров. Страница по умолчанию (Default.aspx) содержит элемент управления, облегчающий связь с лежащей в основе пользовательской STS, которая настроена точно так же, как активная STS.

Веб-узел STS должен проверять подлинность вызывающего перед выдачей маркера и именно здесь, в целях проверки подлинности и авторизации, вступает в дело классическая настройка ASP.NET. На рис. 11 приложение STS настроено на проверку подлинности форм, так что запросы перенаправляются на страницу входа в систему (Login.aspx), если их подлинность еще не была проверена FormsAuthenticationModule.

Пассивная STS может пользоваться той же основной реализацией STS, что и активная STS – с одним небольшим изменением. В переопределении GetScope (показанном на рис. 5) пассивная STS должна установить свойство ReplyToAddress так, чтобы STS могла произвести перенаправление после выдачи маркера. Обычно перенаправление устанавливается на страницу по умолчанию для RP, основанную на адресе AppliesTo, поставляемом с RST:

Scope scope = new Scope(request);
scope.ReplyToAddress = scope.AppliesToAddress + "/default.aspx";
// other scope settings

fig11.gif

Рис. 11. Архитектура реализации для пассивной STS, использующей проверку подлинности форм

Конфигурация платформы Geneva для пассивной STS не отличается от таковой для активной STS. Тип SecurityTokenServiceConfiguration используется для инициализации STS (показан на рис. 7); также рассматриваются любые актуальные параметры в разделе конфигурации <microsoft.identityModel>.

Элемент управления FederatedPassiveTokenService

Платформа Geneva предоставляет элемент управления, реализующий требуемые функции пассивной STS. Это значит, что он обрабатывает запросы HTTP входа и выхода из системы, преобразует каждый запрос в RST и затем вызывает лежащую в основе реализацию STS. Элемент управления также обрабатывает запросы RSTR и выполняет перенаправление к RP, а также написание файла cookie сеанса для проверенных вызывающих.

Разместите этот элемент управления на страницу по умолчанию для пассивной STS и установите его свойство Service («Служба») на пользовательскую реализацию SecurityTokenServiceConfiguration следующим образом:

<idfx:FederatedPassiveTokenService ID="FederatedPassiveTokenService1" 
  runat="server" Service="STS.IdentityProviderSTSConfiguration, STS">
</idfx:FederatedPassiveTokenService>

Этот элемент управления требует, чтобы подлинность пользователя была проверена и удостоверяется в этом в своем событии PreRender. Ожидается, что веб-узел STS настроен соответствующим образом, чтобы обеспечить перенаправление пользователей в другое место для проверки подлинности, перед достижением этой страницы по умолчанию.

Пока проверенные пользователи всегда направляются на эту страницу по умолчанию, для обработки запросов не требуется иных настроек. Элемент управления также предоставляет события Error, PreSignInRequested, PostSignInRequested, PreSignOutRequested и PostSignOutRequested для обработки исключений и для прикрепления запросов входа в систему и выхода из нее.

SessionAuthenticationModule

В качестве альтернативы элементу управления FederatedPassiveTokenService, можно программно включить функции пассивной STS. Сперва включите интегрированную проверку подлинности в разделе конфигурации <microsoft.identityModel>:

<microsoft.identityModel>
  <federatedAuthentication enabled="true"/>
</microsoft.identityModel>

Затем включите модуль интеграции для пассивной STS, SessionAuthenticationModule из пространства имен Microsoft.IdentityModel.Web:

<modules>
  <add name="SessionAuthentication" 
    type="Microsoft.IdentityModel.Web.SessionAuthenticationModule,
    Microsoft.IdentityModel, Version=0.5.1.0,
    Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</modules>

Это даст тот же результат, что и элемент управления FederatedPassiveTokenService для запросов, отсылаемых на любую страницу на веб-узле STS Web. Модуль перенаправляет непроверенных вызывающих на страницу входа в систему. После успешного входа в систему вызывающие перенаправляются на первоначально запрошенную страницу STS. Этот программный подход дает разработчикам дополнительный уровень контроля, сверх предоставляемого элементом управления FederatedPassiveTokenService. Например, модуль предоставляет следующие события для взаимодействия с инициализацией, управлением маркерами безопасности, входом в систему и выходом из нее: ConfigurationLoading, ConfigurationLoaded, SecurityTokenReceived, SecurityTokenValidated, SessionSecurityTokenCreated, SessionSecurityTokenReceived, SignedIn, SigningOut, SignedOut, SignInError и SignOutError.

Проверка подлинности пользователя

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

Пассивная проверка подлинности STS основана на методиках конфигурации ASP.NET. Типичными вариантами являются проверка подлинности Windows, проверка подлинности Forms и проверка подлинности Windows CardSpace. В случае проверки подлинности Windows, используется следующая конфигурация:

<authentication mode="Windows"/>
<authorization>
  <deny users="?"/>
</authorization>

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

Рис. 11 иллюстрирует пример, где используется проверка подлинности Forms. FormsAuthenticationModule перенаправляет вызовы, подлинность которых не проверена, на страницу входа в систему, где пользователь может предоставить учетные данные. После того как проверка подлинности завершена, страница входа произведет перенаправление на страницу STS по умолчанию, где управление интеграцией произведет обработку первоначального запроса. Конфигурация ASP.NET для этого будет выглядеть следующим образом:

<authentication mode="Forms"/>
<authorization>
  <deny users="?"/>
</authorization>

В случае проверки подлинности Windows CardSpace веб-сайт STS может быть настроен на проверку подлинности Forms, но страница входа в систему будет включать в себя элемент управления InformationCard для проверки подлинности Windows CardSpace.

Преобразование заявок

Преобразование заявок имеет ключевое значение для интегрированной информации – и оно может произойти в различных точках потока интеграции. В простом сценарии интеграции, где IP-STS и RP принадлежат к одному и тому же домену, IP-STS отвечает за преобразование заявок из первоначального набора заявок идентификации, представляемых пользователем во время проверки подлинности, на заявки, которые RP может использовать для проверки подлинности вызовов. Пользователи могут предоставить любой из поддерживаемых типов учетных данных для проверки подлинности IP-STS, каждый из них оценивает набор заявок, представляющий учетные данные.

IP-STS преобразует эти заявки в нормализованный набор заявок приложений, на который RP полагается в целях авторизации вызовов – они могут быть ролями или более детализированными заявками, такими как заявки на создание, чтение, обновление или удаление правил. Схема на рис. 12 иллюстрирует подобный сценарий, где администратор входит в систему и получает заявку роли, а также несколько заявок действий, включая Create, Read, Update и Delete (заявки на создание, чтение, обновление и удаление).

fig12.gif

Рис. 12. Преобразование заявок в IP-STS

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

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

В подобных случаях, для RP может быть полезно запрашивать лишь несколько заявок от IP-STS, чтобы определить вызывающего и затем выпустить новый маркер с конкретными набором дополнительных заявок лишь для контекста вызова. Например, если пользователь вызывает операцию DeleteCustomer на службе RP, перед авторизацией доступа к операции RP отправляет вызов к RP-STS передавая маркер от IP-STS и запрашивая заявку удаления в контексте операции DeleteCustomer. Если заявка присутствует, вызов авторизуется. Схема на рис. 13 иллюстрирует этот пример.

Бывают также случаи, когда заявками, выпущенными STS, нельзя напрямую делиться с RP. Например, вместо выпуска заявки возраста, чтобы знать возврат пользователя, RP может выпустить заявку о возрасте старше 13 лет, чтобы гарантировать, что вызывающий является достаточно взрослым для использования функций RP. Таким образом, реальное значение заявки возраста никогда не покидает STS. Само собой, это предполагает, что ST поставляет заявки, избегающие обмена личными данными и, тем не менее, включающие данные, полезные для RP.

fig13.gif

Рис. 13. Преобразование заявок в RP-STS

Преобразование заявок может также иметь место в ситуации интеграции, где пользователям, принадлежащим к одному домену, дается доступ к RP в другом домене. В данном случае задействованы две STS – IP-STS домена пользователя и RP-STS для домена, владеющего RP.

Кроме того, в данном случае IP-STS даст некоторые согласованные заявки, которые RP-STS может понять; однако эти заявки вряд ли будут полезны непосредственно в приложении RP. Вместо этого RP-STS будет отвечать за преобразование еще одного доверенного набора заявок, в заявки, которые понятны в домене RP.

Этот сценарий проиллюстрирован на рис. 14. Когда Джо пытается получить доступ к RP без маркера, он в войдет в систему на IP-STS в собственном домене (Domain B). Запрос будет интересоваться заявками, которые RP понимает, в данном случае RPClaim, так что IP-STS знает, что необходимо выпустить маркер, который RP сможет использовать. Когда RP-STS получает этот маркер, она преобразует заявки в заявки, относящиеся к RP. Чтобы этот интегрированный сценарий сработал, между RP-STS и IP-STS должны существовать отношения доверия и они должны согласиться относительно набора заявок, которые IP-STS должен выпустить для пользователей, которым будет дан доступ в RP.

fig14.gif

Рис. 14. Преобразование заявок в случае интеграции

Заключение

Платформа Geneva – служебная программа, которая весьма кстати для тех, кто заинтересован в создании собственных STS и не нуждается в полнофункциональной платформе STS, такой как Geneva Server. Создание собственной STS – нетривиальная задача, даже с помощью платформы Geneva и для уменьшения уязвимости неизменно рекомендуется использовать полнофункциональную STS.

Вне зависимости от платформы поток сообщений для активной и пассивной реализаций STS остается тем же, точно так же как и идеи, на которых основывается преобразование заявок. Некоторые дополнительные концепции, относящиеся к реализациям STS, включают делегирование идентификации и проверку подлинности с переходом вверх. Образцы и документацию, связанные с этими и другими концепциями, можно найти в SDK Geneva Framework.

Мишель Леру Бустамант (Michele Leroux Bustamante) – главный архитектор компании IDesign Inc., региональный директор корпорации Майкрософт в Сан-Диего и обладатель статуса Microsoft MVP в области Connected Systems. Ее последняя книга – Learning WCF («Изучаем WCF»). С Мишель можно связаться по адресу mlb@idesign.net или на веб-узле idesign.net. Мишель ведет блог веб-узле dasblonde.net.