Delen via


Procedure: Een service maken die gebruikmaakt van een aangepaste certificaatvalidator

In dit onderwerp wordt beschreven hoe u een aangepaste certificaatvalidator implementeert en hoe u client- of servicereferenties configureert om de standaardcertificaatvalidatielogica te vervangen door de aangepaste certificaatvalidator.

Als het X.509-certificaat wordt gebruikt om een client of service te verifiëren, gebruikt Windows Communication Foundation (WCF) standaard het Windows-certificaatarchief en de Crypto-API om het certificaat te valideren en ervoor te zorgen dat het wordt vertrouwd. Soms is de ingebouwde functionaliteit voor certificaatvalidatie niet voldoende en moet deze worden gewijzigd. WCF biedt een eenvoudige manier om de validatielogica te wijzigen door gebruikers toe te staan een aangepast certificaatvalidator toe te voegen. Als er een aangepaste certificaatvalidator is opgegeven, gebruikt WCF niet de ingebouwde certificaatvalidatielogica, maar is in plaats daarvan afhankelijk van de aangepaste validator.

Procedures

Een aangepaste certificaatvalidator maken

  1. Definieer een nieuwe klasse die is afgeleid van X509CertificateValidator.

  2. Implementeer de abstracte Validate methode. Het certificaat dat moet worden gevalideerd, wordt doorgegeven als een argument voor de methode. Als het doorgegeven certificaat niet geldig is volgens de validatielogica, genereert deze methode een SecurityTokenValidationException. Als het certificaat geldig is, keert de methode terug naar de aanroeper.

    Notitie

    Als u verificatiefouten wilt retourneren naar de client, genereert u een FaultException in de Validate methode.

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

Een aangepast certificaatvalidator opgeven in de serviceconfiguratie

  1. Voeg een gedragselement> en een <serviceBehaviors> toe aan het <element system.serviceModel>.<

  2. Voeg een <gedrag> toe en stel het name kenmerk in op een geschikte waarde.

  3. Voeg een <serviceCredentials> toe aan het <behavior> element.

  4. Voeg een <clientCertificate> element toe aan het <serviceCredentials> element.

  5. Voeg een <verificatie> toe aan het <clientCertificate> element.

  6. Stel het customCertificateValidatorType kenmerk in op het validatietype. In het volgende voorbeeld wordt het kenmerk ingesteld op de naamruimte en de naam van het type.

  7. Stel het certificateValidationMode kenmerk in op 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>  
    

Een aangepaste certificaatvalidator opgeven met behulp van configuratie op de client

  1. Voeg een gedragselement> en een <serviceBehaviors> toe aan het <element system.serviceModel>.<

  2. Voeg een <endpointBehaviors-element> toe.

  3. Voeg een <behavior> element toe en stel het name kenmerk in op een juiste waarde.

  4. Voeg een <clientCredentials-element> toe.

  5. Voeg een <serviceCertificate> toe.

  6. Voeg een <verificatie> toe, zoals wordt weergegeven in het volgende voorbeeld.

  7. Stel het customCertificateValidatorType kenmerk in op het validatietype.

  8. Stel het certificateValidationMode kenmerk in op Custom. In het volgende voorbeeld wordt het kenmerk ingesteld op de naamruimte en de naam van het 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>  
    

Een aangepaste certificaatvalidator opgeven met behulp van code op de service

  1. Geef de aangepaste certificaatvalidator op de ClientCertificate eigenschap op. U kunt de servicereferenties openen met behulp van de Credentials eigenschap.

  2. Stel de eigenschap CertificateValidationMode in op 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")

Een aangepaste certificaatvalidator opgeven met behulp van code op de client

  1. Geef de aangepaste certificaatvalidator op met behulp van de CustomCertificateValidator eigenschap. U kunt de clientreferenties openen met behulp van de Credentials eigenschap. (De clientklasse gegenereerd door ServiceModel Metadata Utility Tool (Svcutil.exe) is altijd afgeleid van de ClientBase<TChannel> klasse.)

  2. Stel de eigenschap CertificateValidationMode in op Custom.

Opmerking

Beschrijving

In het volgende voorbeeld ziet u een implementatie van een aangepaste certificaatvalidator en het gebruik ervan op de service.

Code

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

Zie ook