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


Поставщик маркеров SAML

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

  • если используется хранилище учетных данных с которым эти поставщики не работают;

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

  • если строится пользовательский маркер.

В этом примере показано, как создать пользовательский поставщик маркеров, позволяющий использовать токен SAML, полученный из-за пределов клиентской платформы WCF.

Итак, этот образец демонстрирует следующее:

  • как настроить клиент с пользовательским поставщиком маркеров;

  • как передать маркер SAML в пользовательские учетные данные клиента;

  • Как токен SAML предоставляется клиентской платформе WCF.

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

Служба предоставляет две конечные точки для взаимодействия с ней; они определены в файле конфигурации App.config. Каждая конечная точка состоит из адреса, привязки и контракта. Привязка настраивается с помощью стандартного элемента wsFederationHttpBinding, который использует безопасность сообщений. Одна конечная точка ожидает проверки подлинности клиента с помощью маркера SAML, использующего симметричный ключ проверки, в то время как другая ожидает проверки подлинности клиента с помощью маркера SAML, использующего асимметричный ключ проверки. Кроме того, служба настраивает сертификат службы с помощью поведения serviceCredentials. Поведение serviceCredentials позволяет настроить сертификат службы. Сертификат службы используется клиентом для проверки подлинности службы и обеспечения защиты сообщения. В следующей конфигурации делается ссылка на сертификат "localhost", установленный во время установки образца, в соответствии с приведенными в конце раздела инструкциями. Поведение serviceCredentials также позволяет настроить сертификаты для подписи маркеров SAML. Следующая конфигурация ссылается на сертификат "Alice", установленный при выполнении образца.

<system.serviceModel>
 <services>
  <service
          name="Microsoft.ServiceModel.Samples.CalculatorService"
          behaviorConfiguration="CalculatorServiceBehavior">
   <host>
    <baseAddresses>
     <!-- configure base address provided by host -->
     <add
  baseAddress="http://localhost:8000/servicemodelsamples/service/" />
    </baseAddresses>
   </host>
   <!-- use base address provided by host -->
   <!-- Endpoint that expect SAML tokens with Symmetric proof keys -->
   <endpoint address="calc/symm"
             binding="wsFederationHttpBinding"
             bindingConfiguration="Binding1"
             contract="Microsoft.ServiceModel.Samples.ICalculator" />
   <!-- Endpoint that expect SAML tokens with Asymmetric proof keys -->
   <endpoint address="calc/asymm"
             binding="wsFederationHttpBinding"
             bindingConfiguration="Binding2"
             contract="Microsoft.ServiceModel.Samples.ICalculator" />
  </service>
 </services>

 <bindings>
  <wsFederationHttpBinding>
   <!-- Binding that expect SAML tokens with Symmetric proof keys -->
   <binding name="Binding1">
    <security mode="Message">
     <message negotiateServiceCredential ="false"
              issuedKeyType="SymmetricKey"
              issuedTokenType="http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1"  />
    </security>
   </binding>
   <!-- Binding that expect SAML tokens with Asymmetric proof keys -->
   <binding name="Binding2">
    <security mode="Message">
     <message negotiateServiceCredential ="false"
              issuedKeyType="AsymmetricKey"
              issuedTokenType="http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1"  />
    </security>
   </binding>
  </wsFederationHttpBinding>
 </bindings>

 <behaviors>
  <serviceBehaviors>
   <behavior name="CalculatorServiceBehavior">
    <!--
    The serviceCredentials behavior allows one to define a service certificate.
    A service certificate is used by a client to authenticate the service and provide message protection.
    This configuration references the "localhost" certificate installed during the setup instructions.
    -->
    <serviceCredentials>
     <!-- Set allowUntrustedRsaIssuers to true to allow self-signed, asymmetric key based SAML tokens -->
     <issuedTokenAuthentication allowUntrustedRsaIssuers ="true" >
      <!-- Add Alice to the list of certs trusted to issue SAML tokens -->
      <knownCertificates>
       <add storeLocation="LocalMachine"
            storeName="TrustedPeople"
            x509FindType="FindBySubjectName"
            findValue="Alice"/>
      </knownCertificates>
     </issuedTokenAuthentication>
     <serviceCertificate storeLocation="LocalMachine"
                         storeName="My"
                         x509FindType="FindBySubjectName"
                         findValue="localhost"  />
    </serviceCredentials>
   </behavior>
  </serviceBehaviors>
 </behaviors>

</system.serviceModel>

Ниже показано, как разработать пользовательский поставщик токенов SAML и интегрировать его с WCF: платформа безопасности:

  1. Создание пользовательского поставщика маркеров SAML.

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

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

    protected override SecurityToken GetTokenCore(TimeSpan timeout)
    {
     // Create a SamlSecurityToken from the provided assertion
     SamlSecurityToken samlToken = new SamlSecurityToken(assertion);
    
     // Create a SecurityTokenSerializer that will be used to
     // serialize the SamlSecurityToken
     WSSecurityTokenSerializer ser = new WSSecurityTokenSerializer();
     // Create a memory stream to write the serialized token into
     // Use an initial size of 64Kb
     MemoryStream s = new MemoryStream(UInt16.MaxValue);
    
     // Create an XmlWriter over the stream
     XmlWriter xw = XmlWriter.Create(s);
    
     // Write the SamlSecurityToken into the stream
     ser.WriteToken(xw, samlToken);
    
     // Seek back to the beginning of the stream
     s.Seek(0, SeekOrigin.Begin);
    
     // Load the serialized token into a DOM
     XmlDocument dom = new XmlDocument();
     dom.Load(s);
    
     // Create a KeyIdentifierClause for the SamlSecurityToken
     SamlAssertionKeyIdentifierClause samlKeyIdentifierClause = samlToken.CreateKeyIdentifierClause<SamlAssertionKeyIdentifierClause>();
    
    // Return a GenericXmlToken from the XML for the
    // SamlSecurityToken, the proof token, the valid from and valid
    // until times from the assertion and the key identifier clause
    // created above
    return new GenericXmlSecurityToken(dom.DocumentElement, proofToken, assertion.Conditions.NotBefore, assertion.Conditions.NotOnOrAfter, samlKeyIdentifierClause, samlKeyIdentifierClause, null);
    }
    
  2. Создание пользовательского диспетчера маркеров безопасности.

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

    public class SamlSecurityTokenManager : ClientCredentialsSecurityTokenManager
    {
     SamlClientCredentials samlClientCredentials;
    
     public SamlSecurityTokenManager ( SamlClientCredentials samlClientCredentials)
      : base(samlClientCredentials)
     {
      // Store the creating client credentials
      this.samlClientCredentials = samlClientCredentials;
     }
    
     public override SecurityTokenProvider CreateSecurityTokenProvider ( SecurityTokenRequirement tokenRequirement )
     {
      // If token requirement matches SAML token return the
      // custom SAML token provider
      if (tokenRequirement.TokenType == SecurityTokenTypes.Saml ||
          tokenRequirement.TokenType == "http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1")
      {
       // Retrieve the SAML assertion and proof token from the
       // client credentials
       SamlAssertion assertion = this.samlClientCredentials.Assertion;
       SecurityToken prooftoken = this.samlClientCredentials.ProofToken;
    
       // If either the assertion of proof token is null...
       if (assertion == null || prooftoken == null)
       {
        // ...get the SecurityBindingElement and then the
        // specified algorithm suite
        SecurityBindingElement sbe = null;
        SecurityAlgorithmSuite sas = null;
    
        if ( tokenRequirement.TryGetProperty<SecurityBindingElement> ( "http://schemas.microsoft.com/ws/2006/05/servicemodel/securitytokenrequirement/SecurityBindingElement", out sbe))
        {
         sas = sbe.DefaultAlgorithmSuite;
        }
    
        // If the token requirement is for a SymmetricKey based token..
        if (tokenRequirement.KeyType == SecurityKeyType.SymmetricKey)
        {
         // Create a symmetric proof token
         prooftoken = SamlUtilities.CreateSymmetricProofToken ( tokenRequirement.KeySize );
         // and a corresponding assertion based on the claims specified in the client credentials
         assertion = SamlUtilities.CreateSymmetricKeyBasedAssertion ( this.samlClientCredentials.Claims, new X509SecurityToken ( samlClientCredentials.ClientCertificate.Certificate ), new X509SecurityToken ( samlClientCredentials.ServiceCertificate.DefaultCertificate ), (BinarySecretSecurityToken)prooftoken, sas);
        }
        // otherwise...
        else
        {
         // Create an asymmetric proof token
         prooftoken = SamlUtilities.CreateAsymmetricProofToken();
         // and a corresponding assertion based on the claims
         // specified in the client credentials
         assertion = SamlUtilities.CreateAsymmetricKeyBasedAssertion ( this.samlClientCredentials.Claims, prooftoken, sas );
        }
       }
    
       // Create a SamlSecurityTokenProvider based on the assertion and proof token
       return new SamlSecurityTokenProvider(assertion, prooftoken);
      }
      // otherwise use base implementation
      else
      {
       return base.CreateSecurityTokenProvider(tokenRequirement);
      }
    }
    
  3. Создание пользовательских учетных данных клиента.

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

    public class SamlClientCredentials : ClientCredentials
    {
     ClaimSet claims;
     SamlAssertion assertion;
     SecurityToken proofToken;
    
     public SamlClientCredentials() : base()
     {
      // Set SupportInteractive to false to suppress Cardspace UI
      base.SupportInteractive = false;
     }
    
     protected SamlClientCredentials(SamlClientCredentials other) : base ( other )
     {
      // Just do reference copy given sample nature
      this.assertion = other.assertion;
      this.claims = other.claims;
      this.proofToken = other.proofToken;
     }
    
     public SamlAssertion Assertion { get { return assertion; } set { assertion = value; } }
    
     public SecurityToken ProofToken { get { return proofToken; } set { proofToken = value; } }
     public ClaimSet Claims { get { return claims; } set { claims = value; } }
    
     protected override ClientCredentials CloneCore()
     {
      return new SamlClientCredentials(this);
     }
    
     public override SecurityTokenManager CreateSecurityTokenManager()
     {
      // return custom security token manager
      return new SamlSecurityTokenManager(this);
     }
    }
    
  4. Настройка клиента для использования пользовательских учетных данных клиента.

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

    // Create new credentials class
    SamlClientCredentials samlCC = new SamlClientCredentials();
    
    // Set the client certificate. This is the cert that will be used to sign the SAML token in the symmetric proof key case
    samlCC.ClientCertificate.SetCertificate(StoreLocation.CurrentUser, StoreName.My, X509FindType.FindBySubjectName, "Alice");
    
    // Set the service certificate. This is the cert that will be used to encrypt the proof key in the symmetric proof key case
    samlCC.ServiceCertificate.SetDefaultCertificate(StoreLocation.CurrentUser, StoreName.TrustedPeople, X509FindType.FindBySubjectName, "localhost");
    
    // Create some claims to put in the SAML assertion
    IList<Claim> claims = new List<Claim>();
    claims.Add(Claim.CreateNameClaim(samlCC.ClientCertificate.Certificate.Subject));
    ClaimSet claimset = new DefaultClaimSet(claims);
    samlCC.Claims = claimset;
    
    // set new credentials
    client.ChannelFactory.Endpoint.Behaviors.Remove(typeof(ClientCredentials));
    client.ChannelFactory.Endpoint.Behaviors.Add(samlCC);
    

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

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

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

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

  • Создание сертификата сервера.

    Следующие строки из файла Setup.bat создают используемый в дальнейшем сертификат сервера. Переменная %SERVER_NAME%задает имя сервера. Измените эту переменную, чтобы задать собственное имя сервера. По умолчанию в этом пакетном файле используется имя localhost.

    Сертификат хранится в хранилище «My store (Личном хранилище)» в расположении LocalMachine.

    echo ************
    echo Server cert setup starting
    echo %SERVER_NAME%
    echo ************
    echo making server cert
    echo ************
    makecert.exe -sr LocalMachine -ss My -a sha1 -n CN=%SERVER_NAME% -sky exchange -pe
    
  • Установка сертификата сервера в хранилище доверенных сертификатов клиента.

    Следующие строки из файла Setup.bat копируют сертификат сервера в хранилище доверенных лиц клиента. Этот шаг является обязательным, поскольку сертификаты, созданные с помощью программы Makecert.exe, не получают неявного доверия со стороны клиентской системы. Если уже имеется сертификат, имеющий доверенный корневой сертификат клиента, например сертификат, выпущенный корпорацией Майкрософт, выполнять этот шаг по добавлению сертификата сервера в хранилище сертификатов клиента не требуется.

    certmgr.exe -add -r LocalMachine -s My -c -n %SERVER_NAME% -r LocalMachine -s TrustedPeople
    
  • Создание сертификата издателя.

    Следующие строки из файла Setup.bat создают используемый в дальнейшем сертификат издателя. Переменная %USER_NAME% задает имя издателя. Измените эту переменную, чтобы задать собственное имя издателя. По умолчанию в этом пакетном файле используется имя Alice.

    Сертификат хранится в хранилище "My store" в расположении CurrentUser.

    echo ************
    echo Server cert setup starting
    echo %SERVER_NAME%
    echo ************
    echo making server cert
    echo ************
    makecert.exe -sr CurrentUser -ss My -a sha1 -n CN=%USER_NAME% -sky exchange -pe
    
  • Установка сертификата издателя в хранилище доверенных сертификатов сервера.

    Следующие строки из файла Setup.bat копируют сертификат сервера в хранилище доверенных лиц клиента. Этот шаг является обязательным, поскольку сертификаты, созданные с помощью программы Makecert.exe, не получают неявного доверия со стороны клиентской системы. Если уже имеется сертификат, имеющий доверенный корневой сертификат клиента, например сертификат, выпущенный корпорацией Майкрософт, выполнять этот шаг по добавлению сертификата сервера в хранилище сертификатов издателя не требуется.

    certmgr.exe -add -r CurrentUser -s My -c -n %USER_NAME% -r LocalMachine -s TrustedPeople
    

Настройка и сборка образца

  1. Убедитесь, что вы выполнили процедуру однократной установки для примеров Windows Communication Foundation.

  2. Чтобы создать решение, следуйте инструкциям по созданию примеров Windows Communication Foundation.

Примечание.

Если для восстановления конфигурации этого образца используется программа Svcutil.exe, измените имя конечной точки в конфигурации клиента, чтобы оно соответствовало клиентскому коду.

Запуск образца на одном компьютере

  1. Запустите Setup.bat из папки установки примера в командной строке Visual Studio с правами администратора. При этом устанавливаются все сертификаты, необходимые для выполнения образца.

    Примечание.

    Пакетный файл Setup.bat предназначен для запуска из командной строки Visual Studio. Переменная среды PATH в командной строке Visual Studio указывает на каталог, содержащий исполняемые файлы, необходимые скрипту Setup.bat.

  2. Запустите программу Service.exe из папки service\bin.

  3. Запустите программу Client.exe из каталога \client\bin. Действия клиента отображаются в консольном приложении клиента.

  4. Если клиент и служба не могут взаимодействовать, ознакомьтесь с Советы устранения неполадок для примеров WCF.

Запуск образца на нескольких компьютерах

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

  2. Скопируйте файлы служебной программы в каталог службы на компьютере службы. Кроме того, скопируйте файлы Setup.bat и Cleanup.bat на компьютер службы.

  3. Необходимо иметь сертификат сервера с именем субъекта, содержащим полное имя домена компьютера. Для отображения этого нового имени сертификата необходимо обновить файл Service.exe.config. Сертификат сервера можно создать путем изменения пакетного файла Setup.bat. Обратите внимание, что файл setup.bat должен быть запущен в командной строке разработчика для Visual Studio, открытом с правами администратора. Необходимо установить переменную %SERVER_NAME% равной полному имени узла компьютера, используемого для размещения службы.

  4. Скопируйте сертификат сервера в хранилище CurrentUser-TrustedPeople клиента. Выполнять этот шаг не требуется, когда сертификат сервера выдан издателем, которому доверяет клиент.

  5. В файле Service.exe.config компьютера службы измените значение базового адреса для указания полного имени компьютера вместо localhost.

  6. На компьютере службы запустите из командной строки программу Service.exe.

  7. Скопируйте на клиентские компьютеры файлы из папки \client\bin\ в папку языка.

  8. В файле Client.exe.config на клиентском компьютере измените значение адреса конечной точки, чтобы оно соответствовало новому адресу службы.

  9. На клиентском компьютере из командной строки запустите программу Client.exe.

  10. Если клиент и служба не могут взаимодействовать, ознакомьтесь с Советы устранения неполадок для примеров WCF.

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

  1. После завершения работы примера запустите в папке примеров файл Cleanup.bat.