Udostępnij przez


Instrukcje: Tworzenie usługi korzystającej z niestandardowego modułu weryfikacji certyfikatów

W tym temacie pokazano, jak zaimplementować niestandardowy moduł sprawdzania poprawności certyfikatów oraz jak skonfigurować poświadczenia klienta lub usługi w celu zastąpienia domyślnej logiki weryfikacji certyfikatu niestandardowym modułem sprawdzania poprawności certyfikatów.

Jeśli certyfikat X.509 jest używany do uwierzytelniania klienta lub usługi, program Windows Communication Foundation (WCF) domyślnie używa magazynu certyfikatów systemu Windows i interfejsu API kryptograficznego do sprawdzania poprawności certyfikatu i zapewnienia, że jest zaufany. Czasami wbudowana funkcja weryfikacji certyfikatu nie jest wystarczająca i musi zostać zmieniona. Program WCF umożliwia łatwą zmianę logiki weryfikacji, umożliwiając użytkownikom dodawanie niestandardowego modułu sprawdzania poprawności certyfikatów. Jeśli określono niestandardowy moduł sprawdzania poprawności certyfikatów, program WCF nie używa wbudowanej logiki weryfikacji certyfikatów, ale zamiast tego korzysta z niestandardowego modułu sprawdzania poprawności.

z konkretnym obiektem

Aby utworzyć niestandardowy moduł sprawdzania poprawności certyfikatów

  1. Zdefiniuj nową klasę pochodzącą z klasy X509CertificateValidator.

  2. Zaimplementuj metodę abstrakcyjną Validate . Certyfikat, który należy zweryfikować, jest przekazywany jako argument do metody . Jeśli przekazany certyfikat jest nieprawidłowy zgodnie z logiką walidacji, ta metoda zgłasza błąd SecurityTokenValidationException. Jeśli certyfikat jest prawidłowy, metoda zwraca element wywołujący.

    Uwaga

    Aby zwrócić błędy uwierzytelniania z powrotem do klienta, należy zgłosić FaultException wartość w metodzie Validate .

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

Aby określić niestandardowy moduł sprawdzania poprawności certyfikatów w konfiguracji usługi

  1. Dodaj element behaviors> i <serviceBehaviors> do <elementu system.serviceModel>.<

  2. <Dodaj zachowanie> i ustaw name atrybut na odpowiednią wartość.

  3. Dodaj element serviceCredentials><behavior>.<

  4. <clientCertificate> Dodaj element do <serviceCredentials> elementu .

  5. <Dodaj uwierzytelnianie> do <clientCertificate> elementu .

  6. customCertificateValidatorType Ustaw atrybut na typ modułu sprawdzania poprawności. Poniższy przykład ustawia atrybut na przestrzeń nazw i nazwę typu.

  7. certificateValidationMode Ustaw atrybut na 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>  
    

Aby określić niestandardowy moduł sprawdzania poprawności certyfikatów przy użyciu konfiguracji na kliencie

  1. Dodaj element behaviors> i <serviceBehaviors> do <elementu system.serviceModel>.<

  2. <Dodaj element endpointBehaviors>.

  3. <behavior> Dodaj element i ustaw name atrybut na odpowiednią wartość.

  4. <Dodaj element clientCredentials>.

  5. Dodaj usługęCertyfikat><.

  6. <Dodaj uwierzytelnianie>, jak pokazano w poniższym przykładzie.

  7. customCertificateValidatorType Ustaw atrybut na typ modułu sprawdzania poprawności.

  8. certificateValidationMode Ustaw atrybut na Custom. Poniższy przykład ustawia atrybut na przestrzeń nazw i nazwę 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>  
    

Aby określić niestandardowy moduł sprawdzania poprawności certyfikatu przy użyciu kodu w usłudze

  1. Określ niestandardowy moduł sprawdzania poprawności certyfikatów we ClientCertificate właściwości . Możesz uzyskać dostęp do poświadczeń usługi przy użyciu Credentials właściwości .

  2. Ustaw właściwość 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")

Aby określić niestandardowy moduł sprawdzania poprawności certyfikatu przy użyciu kodu na kliencie

  1. Określ niestandardowy moduł sprawdzania poprawności certyfikatów CustomCertificateValidator przy użyciu właściwości . Dostęp do poświadczeń klienta można uzyskać przy użyciu Credentials właściwości . (Klasa klienta wygenerowana przez Narzędzie ServiceModel Metadata Tool (Svcutil.exe) zawsze pochodzi z ClientBase<TChannel> klasy .

  2. Ustaw właściwość CertificateValidationMode na Custom.

Przykład

opis

Poniższy przykład przedstawia implementację niestandardowego modułu sprawdzania poprawności certyfikatu i jego użycia w usłudze.

Kod

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

Zobacz też