Share via


Postupy: Vytvoření služby, která používá vlastní validátor certifikátů

Toto téma ukazuje, jak implementovat vlastní validátor certifikátu a jak nakonfigurovat přihlašovací údaje klienta nebo služby tak, aby nahradily výchozí logiku ověření certifikátu vlastním validátorem certifikátu.

Pokud se certifikát X.509 používá k ověření klienta nebo služby, windows Communication Foundation (WCF) ve výchozím nastavení používá úložiště certifikátů Systému Windows a rozhraní Crypto API k ověření certifikátu a k zajištění, že je důvěryhodný. Někdy není integrovaná funkce ověření certifikátu dostatečná a je nutné ji změnit. WCF poskytuje snadný způsob, jak změnit logiku ověřování tím, že uživatelům umožní přidat vlastní validátor certifikátu. Pokud je zadán vlastní validátor certifikátu, WCF nepoužívá předdefinovanou logiku ověření certifikátu, ale spoléhá na vlastní validátor.

Procedury

Vytvoření vlastního validátoru certifikátu

  1. Definujte novou třídu odvozenou z X509CertificateValidator.

  2. Implementujte abstraktní Validate metodu. Certifikát, který musí být ověřen, je předán jako argument metodě. Pokud předaný certifikát není platný podle ověřovací logiky SecurityTokenValidationException, tato metoda vyvolá výjimku . Pokud je certifikát platný, metoda se vrátí volajícímu.

    Poznámka:

    Pokud chcete vrátit chyby ověřování zpět klientovi, vyvolte metodu FaultExceptionValidate .

public class MyX509CertificateValidator : X509CertificateValidator
{
    string allowedIssuerName;

    public MyX509CertificateValidator(string allowedIssuerName)
    {
        if (allowedIssuerName == null)
        {
            throw new ArgumentNullException("allowedIssuerName");
        }

        this.allowedIssuerName = allowedIssuerName;
    }

    public override void Validate(X509Certificate2 certificate)
    {
        // Check that there is a certificate.
        if (certificate == null)
        {
            throw new ArgumentNullException("certificate");
        }

        // Check that the certificate issuer matches the configured issuer.
        if (allowedIssuerName != certificate.IssuerName.Name)
        {
            throw new SecurityTokenValidationException
              ("Certificate was not issued by a trusted issuer");
        }
    }
}
Public Class MyX509CertificateValidator
    Inherits X509CertificateValidator
    Private allowedIssuerName As String

    Public Sub New(ByVal allowedIssuerName As String)
        If allowedIssuerName Is Nothing Then
            Throw New ArgumentNullException("allowedIssuerName")
        End If

        Me.allowedIssuerName = allowedIssuerName

    End Sub

    Public Overrides Sub Validate(ByVal certificate As X509Certificate2)
        ' Check that there is a certificate.
        If certificate Is Nothing Then
            Throw New ArgumentNullException("certificate")
        End If

        ' Check that the certificate issuer matches the configured issuer.
        If allowedIssuerName <> certificate.IssuerName.Name Then
            Throw New SecurityTokenValidationException _
              ("Certificate was not issued by a trusted issuer")
        End If

    End Sub
End Class

Určení vlastního validátoru certifikátu v konfiguraci služby

  1. Přidání elementu behaviors> a< serviceBehaviors> do elementu <system.serviceModel.><

  2. <Přidejte chování> a nastavte name atribut na odpovídající hodnotu.

  3. Přidejte do elementu <<behavior> serviceCredentials.>

  4. <clientCertificate> Přidejte do elementu <serviceCredentials> prvek.

  5. Přidejte do elementu <<clientCertificate> ověřování.>

  6. customCertificateValidatorType Nastavte atribut na typ validátoru. Následující příklad nastaví atribut na obor názvů a název typu.

  7. Nastavte atribut na certificateValidationModeCustom.

    <configuration>  
     <system.serviceModel>  
      <behaviors>  
       <serviceBehaviors>  
        <behavior name="ServiceBehavior">  
         <serviceCredentials>  
          <clientCertificate>  
          <authentication certificateValidationMode="Custom" customCertificateValidatorType="Samples.MyValidator, service" />  
          </clientCertificate>  
         </serviceCredentials>  
        </behavior>  
       </serviceBehaviors>  
      </behaviors>  
    </system.serviceModel>  
    </configuration>  
    

Určení vlastního validátoru certifikátu pomocí konfigurace v klientovi

  1. Přidání elementu behaviors> a< serviceBehaviors> do elementu <system.serviceModel.><

  2. Přidání elementu <endpointBehaviors>

  3. <behavior> Přidejte prvek a nastavte name atribut na odpovídající hodnotu.

  4. Přidání elementu <clientCredentials>

  5. <Přidejte serviceCertificate>.

  6. <Přidejte ověřování>, jak je znázorněno v následujícím příkladu.

  7. customCertificateValidatorType Nastavte atribut na typ validátoru.

  8. Nastavte atribut na certificateValidationModeCustom. Následující příklad nastaví atribut na obor názvů a název typu.

    <configuration>  
     <system.serviceModel>  
      <behaviors>  
       <endpointBehaviors>  
        <behavior name="clientBehavior">  
         <clientCredentials>  
          <serviceCertificate>  
           <authentication certificateValidationMode="Custom"
                  customCertificateValidatorType=  
             "Samples.CustomX509CertificateValidator, client"/>  
          </serviceCertificate>  
         </clientCredentials>  
        </behavior>  
       </endpointBehaviors>  
      </behaviors>  
     </system.serviceModel>  
    </configuration>  
    

Určení vlastního validátoru certifikátu pomocí kódu ve službě

  1. Zadejte vlastní validátor certifikátu ve ClientCertificate vlastnosti. K přihlašovacím údajům služby můžete přistupovat pomocí Credentials vlastnosti.

  2. Nastavte vlastnost CertificateValidationMode na Custom.

serviceHost.Credentials.ClientCertificate.Authentication.CertificateValidationMode =
    X509CertificateValidationMode.Custom;
serviceHost.Credentials.ClientCertificate.Authentication.CustomCertificateValidator =
    new MyX509CertificateValidator("CN=Contoso.com");
serviceHost.Credentials.ClientCertificate.Authentication. _
    CertificateValidationMode = X509CertificateValidationMode.Custom
serviceHost.Credentials.ClientCertificate.Authentication. _
   CustomCertificateValidator = New MyX509CertificateValidator("CN=Contoso.com")

Určení vlastního validátoru certifikátu pomocí kódu v klientovi

  1. Zadejte vlastní validátor certifikátu pomocí CustomCertificateValidator vlastnosti. K přihlašovacím údajům klienta můžete přistupovat pomocí Credentials vlastnosti. (Třída klienta vygenerovaná pomocí Nástroj ServiceModel Metadata Utility (Svcutil.exe) je vždy odvozen od ClientBase<TChannel> třídy.)

  2. Nastavte vlastnost CertificateValidationMode na Custom.

Příklad

Popis

Následující ukázka ukazuje implementaci vlastního validátoru certifikátu a jeho použití ve službě.

Kód

using System;
using System.IdentityModel.Selectors;
using System.IdentityModel.Tokens;
using System.Security.Cryptography.X509Certificates;
using System.ServiceModel;
using System.ServiceModel.Security;

namespace Microsoft.ServiceModel.Samples
{
    [ServiceContract(Namespace="http://Microsoft.ServiceModel.Samples")]
    public interface ICalculator
    {
        [OperationContract]
        double Add(double n1, double n2);
    }

    public class CalculatorService : ICalculator
    {
        public double Add(double n1, double n2)
        {
            double result = n1 + n2;
            return result;
        }
    }

    class Program
    {
        static void Main()
        {
            using (ServiceHost serviceHost = new ServiceHost(typeof(CalculatorService)))
            {
                serviceHost.Credentials.ClientCertificate.Authentication.CertificateValidationMode =
                    X509CertificateValidationMode.Custom;
                serviceHost.Credentials.ClientCertificate.Authentication.CustomCertificateValidator =
                    new MyX509CertificateValidator("CN=Contoso.com");

                serviceHost.Open();
                Console.WriteLine("Service started, press ENTER to stop ...");
                Console.ReadLine();

                serviceHost.Close();
            }
        }
    }

    public class MyX509CertificateValidator : X509CertificateValidator
    {
        string allowedIssuerName;

        public MyX509CertificateValidator(string allowedIssuerName)
        {
            if (allowedIssuerName == null)
            {
                throw new ArgumentNullException("allowedIssuerName");
            }

            this.allowedIssuerName = allowedIssuerName;
        }

        public override void Validate(X509Certificate2 certificate)
        {
            // Check that there is a certificate.
            if (certificate == null)
            {
                throw new ArgumentNullException("certificate");
            }

            // Check that the certificate issuer matches the configured issuer.
            if (allowedIssuerName != certificate.IssuerName.Name)
            {
                throw new SecurityTokenValidationException
                  ("Certificate was not issued by a trusted issuer");
            }
        }
    }
}
Imports System.IdentityModel.Selectors
Imports System.Security.Cryptography.X509Certificates
Imports System.ServiceModel
Imports System.ServiceModel.Security
Imports System.IdentityModel.Tokens
Imports System.Security.Permissions

<ServiceContract([Namespace]:="http://Microsoft.ServiceModel.Samples")> _
Public Interface ICalculator
    <OperationContract()> _
    Function Add(ByVal n1 As Double, ByVal n2 As Double) As Double
End Interface


Public Class CalculatorService
    Implements ICalculator

    Public Function Add(ByVal n1 As Double, ByVal n2 As Double) As Double _
       Implements ICalculator.Add
        Dim result As Double = n1 + n2
        Return result
    End Function
End Class


Class Program

    Shared Sub Main()
        Dim serviceHost As New ServiceHost(GetType(CalculatorService))
        Try
            serviceHost.Credentials.ClientCertificate.Authentication. _
                CertificateValidationMode = X509CertificateValidationMode.Custom
            serviceHost.Credentials.ClientCertificate.Authentication. _
               CustomCertificateValidator = New MyX509CertificateValidator("CN=Contoso.com")
            serviceHost.Open()
            Console.WriteLine("Service started, press ENTER to stop ...")
            Console.ReadLine()

            serviceHost.Close()
        Finally
            serviceHost.Close()
        End Try

    End Sub
End Class

Public Class MyX509CertificateValidator
    Inherits X509CertificateValidator
    Private allowedIssuerName As String

    Public Sub New(ByVal allowedIssuerName As String)
        If allowedIssuerName Is Nothing Then
            Throw New ArgumentNullException("allowedIssuerName")
        End If

        Me.allowedIssuerName = allowedIssuerName

    End Sub

    Public Overrides Sub Validate(ByVal certificate As X509Certificate2)
        ' Check that there is a certificate.
        If certificate Is Nothing Then
            Throw New ArgumentNullException("certificate")
        End If

        ' Check that the certificate issuer matches the configured issuer.
        If allowedIssuerName <> certificate.IssuerName.Name Then
            Throw New SecurityTokenValidationException _
              ("Certificate was not issued by a trusted issuer")
        End If

    End Sub
End Class

Viz také