Поделиться через


Поставщик устойчивых токенов

В примере DurableIssuedTokenProvider показано, как реализовать пользовательский поставщик выданных токенов.

Обсуждение

Поставщик токенов в Windows Communication Foundation (WCF) используется для предоставления учетных данных инфраструктуре безопасности. Поставщик токенов в целом проверяет целевой объект и выдает соответствующие учетные данные, чтобы инфраструктура безопасности могли защитить сообщение. WCF поставляется с поставщиком токенов CardSpace. Поставщики пользовательских токенов полезны в следующих случаях:

  • Если у вас есть хранилище учетных данных, с которым не может работать встроенный поставщик токенов.

  • Если вы хотите предоставить собственный пользовательский механизм для преобразования учетных данных, начиная с момента, когда пользователь предоставляет сведения, до момента, когда клиент WCF использует эти учетные данные.

  • Если вы создаете пользовательский токен.

В этом примере показано, как создать пользовательский поставщик маркеров, который кэширует маркеры, выданные службой маркеров безопасности (STS).

В этом примере показано следующее:

  • Как клиент может быть настроен с помощью пользовательского поставщика токенов.

  • Как можно кэшировать и предоставлять выданные токены клиенту WCF.

  • Как сервер проходит проверку подлинности клиентом с помощью сертификата X.509 сервера.

Этот пример состоит из клиентской консольной программы (Client.exe), консольной программы службы маркеров безопасности (Securitytokenservice.exe) и консольной программы службы (Service.exe). Служба реализует контракт, определяющий шаблон связи с запросом и ответом. Контракт определяется интерфейсом ICalculator , который предоставляет математические операции (добавление, вычитание, умножение и деление). Клиент получает токен безопасности от службы маркеров безопасности (STS) и выполняет синхронные запросы к этой службе для выполнения заданной математической операции, а служба отвечает результатом. Действие клиента отображается в окне консоли.

Замечание

Инструкции по настройке и сборке этого примера находятся в конце этого раздела.

Этот пример предоставляет контракт ICalculator с помощью <wsHttpBinding>. Конфигурация этой привязки на клиенте показана в следующем коде.

<bindings>
  <wsFederationHttpBinding>
    <binding name="ServiceFed">
      <security mode="Message">
        <message issuedKeyType="SymmetricKey"
                 issuedTokenType="http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1">
          <issuer address="http://localhost:8000/sts/windows"
                  binding="wsHttpBinding" />
        </message>
      </security>
    </binding>
  </wsFederationHttpBinding>
</bindings>

Значение security элемента wsFederationHttpBinding в mode настраивает, какой режим безопасности следует использовать. В этом примере используется безопасность сообщений, поэтому message элемент wsFederationHttpBinding указан внутри security элемента wsFederationHttpBinding. Элемент issuerwsFederationHttpBinding внутри элемента messagewsFederationHttpBinding указывает адрес и связывание для службы токенов безопасности, которая выдает маркер безопасности клиенту, чтобы клиент смог пройти проверку подлинности в службе калькулятора.

Конфигурация этой привязки в службе показана в следующем коде.

<bindings>
  <wsFederationHttpBinding>
    <binding name="ServiceFed">
      <security mode="Message">
        <message issuedKeyType="SymmetricKey"
                 issuedTokenType="http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1">
          <issuerMetadata address="http://localhost:8000/sts/mex">
            <identity>
              <certificateReference storeLocation="CurrentUser"
                                    storeName="TrustedPeople"
                                    x509FindType="FindBySubjectDistinguishedName"
                                    findValue="CN=STS" />
            </identity>
          </issuerMetadata>
        </message>
      </security>
    </binding>
  </wsFederationHttpBinding>
</bindings>

Значение security элемента wsFederationHttpBinding в mode настраивает, какой режим безопасности следует использовать. В этом примере используется безопасность сообщений, поэтому message элемент wsFederationHttpBinding указан внутри security элемента wsFederationHttpBinding. Элемент issuerMetadatawsFederationHttpBinding внутри элемента messagewsFederationHttpBinding указывает адрес и идентификацию конечной точки, которую можно использовать для получения метаданных службы безопасности токенов.

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

<behavior name="ServiceBehavior">
  <serviceDebug includeExceptionDetailInFaults="true" />
  <serviceMetadata httpGetEnabled="true" />
  <serviceCredentials>
    <issuedTokenAuthentication>
      <knownCertificates>
        <add storeLocation="LocalMachine"
              storeName="TrustedPeople"
              x509FindType="FindBySubjectDistinguishedName"
              findValue="CN=STS" />
      </knownCertificates>
    </issuedTokenAuthentication>
    <serviceCertificate storeLocation="LocalMachine"
                        storeName="My"
                        x509FindType="FindBySubjectDistinguishedName"
                        findValue="CN=localhost" />
  </serviceCredentials>
</behavior>

Элемент issuedTokenAuthentication, находящийся внутри элемента serviceCredentials, позволяет службе задавать ограничения на токены, которые клиенты могут предоставлять во время аутентификации. Эта конфигурация указывает, что маркеры, подписанные сертификатом, имя субъекта которого — CN=STS, принимаются службой.

Служба токенов безопасности предоставляет одну конечную точку, используя стандартный wsHttpBinding. Служба токенов безопасности отвечает на запросы клиентов по поводу токенов и, при условии, что клиент проходит аутентификацию с помощью учетной записи в Windows, выдает токен, содержащий имя пользователя клиента как часть утверждений в выданном токене. В рамках создания маркера служба маркеров безопасности подписывает маркер с помощью закрытого ключа, связанного с сертификатом CN=STS. Кроме того, он создает симметричный ключ и шифрует его с помощью открытого ключа, связанного с сертификатом CN=localhost. При возврате токена клиенту служба безопасности токенов также возвращает симметричный ключ. Клиент представляет выданный маркер службе калькулятора и подтверждает, что он знает симметричный ключ, подписав сообщение с этим ключом.

Настраиваемые учетные данные клиента и провайдер токенов

В следующих шагах показано, как разработать пользовательский поставщик токенов, который кэширует выданные токены и интегрировать его с WCF для обеспечения безопасности.

Разработка пользовательского поставщика токенов

  1. Напишите настраиваемый поставщик токенов.

    В примере реализуется пользовательский поставщик маркеров, который возвращает маркер безопасности, полученный из кэша.

    Для выполнения этой задачи поставщик настраиваемых маркеров наследует SecurityTokenProvider класс и переопределяет GetTokenCore метод. Этот метод пытается получить маркер из кэша или, если маркер не найден в кэше, извлекает маркер из базового поставщика, а затем кэширует этот маркер. В обоих случаях метод возвращает значение SecurityToken.

    protected override SecurityToken GetTokenCore(TimeSpan timeout)
    {
      GenericXmlSecurityToken token;
      if (!this.cache.TryGetToken(target, issuer, out token))
      {
        token = (GenericXmlSecurityToken) this.innerTokenProvider.GetToken(timeout);
        this.cache.AddToken(token, target, issuer);
      }
      return token;
    }
    
  2. Напишите пользовательский менеджер токенов безопасности.

    SecurityTokenManager используется для создания SecurityTokenProvider для конкретного SecurityTokenRequirement, который передан ему в методе CreateSecurityTokenProvider. Диспетчер токенов безопасности также используется для создания аутентификаторов токенов и сериализаторов токенов, но они не охвачены этим примером. В этом примере пользовательский диспетчер токенов безопасности наследует от класса ClientCredentialsSecurityTokenManager и переопределяет метод CreateSecurityTokenProvider для возврата пользовательского поставщика токенов, когда переданные требования к токену указывают, что запрашивается выданный токен.

    class DurableIssuedTokenClientCredentialsTokenManager :
     ClientCredentialsSecurityTokenManager
    {
      IssuedTokenCache cache;
    
      public DurableIssuedTokenClientCredentialsTokenManager ( DurableIssuedTokenClientCredentials creds ): base(creds)
      {
        this.cache = creds.IssuedTokenCache;
      }
    
      public override SecurityTokenProvider CreateSecurityTokenProvider ( SecurityTokenRequirement tokenRequirement )
      {
        if (IsIssuedSecurityTokenRequirement(tokenRequirement))
        {
          return new DurableIssuedSecurityTokenProvider ((IssuedSecurityTokenProvider)base.CreateSecurityTokenProvider( tokenRequirement), this.cache);
        }
        else
        {
          return base.CreateSecurityTokenProvider(tokenRequirement);
        }
      }
    }
    
  3. Напишите пользовательские учетные данные клиента.

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

    public class DurableIssuedTokenClientCredentials : ClientCredentials
    {
      IssuedTokenCache cache;
    
      public DurableIssuedTokenClientCredentials() : base()
      {
      }
    
      DurableIssuedTokenClientCredentials ( DurableIssuedTokenClientCredentials other) : base(other)
      {
        this.cache = other.cache;
      }
    
      public IssuedTokenCache IssuedTokenCache
      {
        get
        {
          return this.cache;
        }
        set
        {
          this.cache = value;
        }
      }
    
      protected override ClientCredentials CloneCore()
      {
        return new DurableIssuedTokenClientCredentials(this);
      }
    
      public override SecurityTokenManager CreateSecurityTokenManager()
      {
        return new DurableIssuedTokenClientCredentialsTokenManager ((DurableIssuedTokenClientCredentials)this.Clone());
      }
    }
    
  4. Реализуйте кэш токенов. В примере реализации используется абстрактный базовый класс, с помощью которого потребители заданного кэша маркеров взаимодействуют с кэшем.

    public abstract class IssuedTokenCache
    {
      public abstract void AddToken ( GenericXmlSecurityToken token, EndpointAddress target, EndpointAddress issuer);
      public abstract bool TryGetToken(EndpointAddress target, EndpointAddress issuer, out GenericXmlSecurityToken cachedToken);
    }
    // Configure the client to use the custom client credential.
    

    Для использования пользовательских учетных данных клиента пример удаляет класс учетных данных клиента по умолчанию и предоставляет новый класс учетных данных клиента.

    clientFactory.Endpoint.Behaviors.Remove<ClientCredentials>();
    DurableIssuedTokenClientCredentials durableCreds = new DurableIssuedTokenClientCredentials();
    durableCreds.IssuedTokenCache = cache;
    durableCreds.ServiceCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.PeerOrChainTrust;
    clientFactory.Endpoint.Behaviors.Add(durableCreds);
    

Запуск примера

См. следующие инструкции для запуска примера. При запуске примера запрос маркера безопасности отображается в окне консоли службы маркеров безопасности. Запросы и ответы операции отображаются в окнах клиентской и служебной консоли. Нажмите клавишу ВВОД в любом из окон консоли, чтобы завершить работу приложения.

Пакетный файл Setup.cmd

Пакетный файл Setup.cmd, включенный в этот пример, позволяет настроить серверную и службу маркеров безопасности с соответствующими сертификатами для запуска локального приложения. Пакетный файл создает два сертификата в хранилище сертификатов CurrentUser/TrustedPeople. Первый сертификат имеет имя субъекта CN=STS и используется службой токенов безопасности для подписывания токенов безопасности, которые он выдает клиенту. Второй сертификат имеет имя субъекта CN=localhost и используется службой маркеров безопасности для шифрования секрета, чтобы служба могла расшифровать его.

Настройка, сборка и запуск примера

  1. Запустите файл Setup.cmd, чтобы создать необходимые сертификаты.

  2. Чтобы создать решение, следуйте инструкциям по созданию примеров Windows Communication Foundation. Убедитесь, что все проекты в решении созданы (Shared, RSTRSTR, Service, SecurityTokenService и Client).

  3. Убедитесь, что Service.exe и SecurityTokenService.exe работают с правами администратора.

  4. Запустите Client.exe.

Очистка после образца

Запустите Cleanup.cmd в папке образцов после того, как вы завершите выполнение образца.