Vorgehensweise: Erstellen eines Dienstes, der ein benutzerdefiniertes Zertifikats-Validierungssteuerelement verwendetHow to: Create a Service that Employs a Custom Certificate Validator

In diesem Thema wird gezeigt, wie Sie ein benutzerdefiniertes Zertifikats-Validierungssteuerelement implementieren und wie Sie Anmeldeinformationen für Clients oder Dienste konfigurieren, um die standardmäßige Zertifikatüberprüfungslogik durch das benutzerdefinierte Zertifikats-Validierungssteuerelement zu ersetzen.This topic shows how to implement a custom certificate validator and how to configure client or service credentials to replace the default certificate validation logic with the custom certificate validator.

Wenn das X.509-Zertifikat verwendet wird, um einen Client oder Dienst zu authentifizieren, nutzt Windows Communication Foundation (WCF)Windows Communication Foundation (WCF) standardmäßig den Windows-Zertifikatspeicher und die Kryptografie-API, um das Zertifikat zu überprüfen und sicherzustellen, dass es vertrauenswürdig ist.If the X.509 certificate is used to authenticate a client or service, Windows Communication Foundation (WCF)Windows Communication Foundation (WCF) by default uses the Windows certificate store and Crypto API to validate the certificate and to ensure that it is trusted. Es kann vorkommen, dass die integrierten Funktionen zur Zertifikatsvalidierung nicht ausreichen und geändert werden müssen.Sometimes the built-in certificate validation functionality is not enough and must be changed. WCFWCF bietet eine einfache Möglichkeit zum Ändern der Validierungslogik, indem es Benutzern erlaubt wird, ein benutzerdefiniertes Zertifikats-Validierungssteuerelement hinzuzufügen. provides an easy way to change the validation logic by allowing users to add a custom certificate validator. Wenn Sie ein benutzerdefiniertes Zertifikats-Validierungssteuerelement angeben, verwendet WCFWCF nicht die integrierte Validierungslogik für Zertifikate, sondern nutzt stattdessen das benutzerdefinierte Validierungssteuerelement.If a custom certificate validator is specified, WCFWCF does not use the built-in certificate validation logic but relies on the custom validator instead.

VerfahrenProcedures

So erstellen Sie ein benutzerdefiniertes Zertifikats-ValidierungssteuerelementTo create a custom certificate validator

  1. Definieren Sie eine neue Klasse, die von X509CertificateValidator abgeleitet ist.Define a new class derived from X509CertificateValidator.

  2. Implementieren Sie die abstrakte Validate-Methode.Implement the abstract Validate method. Das Zertifikat, das überprüft werden muss, wird als Argument an die Methode übergeben.The certificate that must be validated is passed as an argument to the method. Wenn das übergebene Zertifikat gemäß der Validierungslogik nicht gültig ist, löst diese Methode eine SecurityTokenValidationException aus.If the passed certificate is not valid according to the validation logic, this method throws a SecurityTokenValidationException. Wenn das Zertifikat gültig ist, gibt die Methode einen Wert an den Aufrufer zurück.If the certificate is valid, the method returns to the caller.

    Hinweis

    Um dem Client Authentifizierungsfehler zurückzugeben, lösen Sie in der FaultException-Methode eine Validate aus.To return authentication errors back to the client, throw a FaultException in the Validate method.

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 

So geben Sie bei der Dienstkonfiguration ein benutzerdefiniertes Zertifikats-Validierungssteuerelement anTo specify a custom certificate validator in service configuration

  1. Hinzufügen einer <Verhalten > Element und ein <ServiceBehaviors > auf die <system.serviceModel > Element.Add a <behaviors> element and a <serviceBehaviors> to the <system.serviceModel> element.

  2. Hinzufügen einer <Verhalten > und legen Sie die name -Attribut auf einen geeigneten Wert.Add a <behavior> and set the name attribute to an appropriate value.

  3. Hinzufügen einer <ServiceCredentials > auf die <behavior> Element.Add a <serviceCredentials> to the <behavior> element.

  4. Fügen Sie dem <clientCertificate>-Element ein <serviceCredentials>-Element hinzu.Add a <clientCertificate> element to the <serviceCredentials> element.

  5. Hinzufügen einer <Authentifizierung > auf die <clientCertificate> Element.Add an <authentication> to the <clientCertificate> element.

  6. Legen Sie das customCertificateValidatorType-Attribut auf den Validierungssteuerelementtyp fest.Set the customCertificateValidatorType attribute to the validator type. Im folgenden Beispiel wird das Attribut auf den Namespace und den Namen des Typs festgelegt.The following example sets the attribute to the namespace and name of the type.

  7. Legen Sie das certificateValidationMode-Attribut auf Custom fest.Set the certificateValidationMode attribute to Custom.

    <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>  
    

So geben Sie ein benutzerdefiniertes Zertifikats-Validierungssteuerelement an, indem Sie die Konfiguration auf dem Client verwendenTo specify a custom certificate validator using configuration on the client

  1. Hinzufügen einer <Verhalten > Element und ein <ServiceBehaviors > auf die <system.serviceModel > Element.Add a <behaviors> element and a <serviceBehaviors> to the <system.serviceModel> element.

  2. Hinzufügen einer <EndpointBehaviors > Element.Add an <endpointBehaviors> element.

  3. Fügen Sie ein <behavior>-Element hinzu, und legen Sie das name-Attribut auf einen passenden Wert fest.Add a <behavior> element and set the name attribute to an appropriate value.

  4. Hinzufügen einer <ClientCredentials > Element.Add a <clientCredentials> element.

  5. Hinzufügen einer <ServiceCertificate >.Add a <serviceCertificate>.

  6. Hinzufügen einer <Authentifizierung > wie im folgenden Beispiel gezeigt.Add an <authentication> as shown on the following example.

  7. Legen Sie das customCertificateValidatorType-Attribut auf den Validierungssteuerelementtyp fest.Set the customCertificateValidatorType attribute to the validator type.

  8. Legen Sie das certificateValidationMode-Attribut auf Custom fest.Set the certificateValidationMode attribute to Custom. Im folgenden Beispiel wird das Attribut auf den Namespace und den Namen des Typs festgelegt.The following example sets the attribute to the namespace and name of the type.

    <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>  
    

So geben Sie ein benutzerdefiniertes Zertifikats-Validierungssteuerelement an, indem Sie Code auf der Dienstseite verwendenTo specify a custom certificate validator using code on the service

  1. Geben Sie das benutzerdefinierte Zertifikats-Validierungssteuerelement über die ClientCertificate-Eigenschaft an.Specify the custom certificate validator on the ClientCertificate property. Sie können auf die Dienstanmeldeinformationen mit der Credentials-Eigenschaft zugreifen.You can access the service credentials using the Credentials property.

  2. Legen Sie die CertificateValidationMode-Eigenschaft auf Custom fest.Set the CertificateValidationMode property to 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")

So geben Sie ein benutzerdefiniertes Zertifikats-Validierungssteuerelement an, indem Sie Code auf der Clientseite verwendenTo specify a custom certificate validator using code on the client

  1. Geben Sie das benutzerdefinierte Zertifikats-Validierungssteuerelement über die CustomCertificateValidator-Eigenschaft an.Specify the custom certificate validator using the CustomCertificateValidator property. Sie können auf die Clientanmeldeinformationen mit der Credentials-Eigenschaft zugreifen.You can access the client credentials using the Credentials property. (Die Client-Klasse, die von generierten ServiceModel Metadata Utility Tool (Svcutil.exe) immer leitet sich von der ClientBase<TChannel> Klasse.)(The client class generated by ServiceModel Metadata Utility Tool (Svcutil.exe) always derives from the ClientBase<TChannel> class.)

  2. Legen Sie die CertificateValidationMode-Eigenschaft auf Custom fest.Set the CertificateValidationMode property to Custom.

BeispielExample

BeschreibungDescription

Das folgende Beispiel zeigt eine Implementierung eines benutzerdefinierten Zertifikats-Validierungssteuerelements und seine Verwendung für den Dienst.The following sample shows an implementation of a custom certificate validator and its usage on the service.

CodeCode

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

using System.Security.Permissions;

[assembly: SecurityPermission(
   SecurityAction.RequestMinimum, Execution = true)]
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
Imports System.IdentityModel.Selectors
Imports System.Security.Cryptography.X509Certificates
Imports System.ServiceModel
Imports System.ServiceModel.Security
Imports System.IdentityModel.Tokens
Imports System.Security.Permissions

<assembly: SecurityPermission(SecurityAction.RequestMinimum, Execution := True)>
<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 

Siehe auchSee Also

X509CertificateValidator