Dela via


Anvisningar: Skapa en tjänst som använder en anpassad certifikatverifierare

Det här avsnittet visar hur du implementerar en anpassad certifikatverifierare och hur du konfigurerar klient- eller tjänstautentiseringsuppgifter för att ersätta standardlogik för certifikatverifiering med den anpassade certifikatverifieringen.

Om X.509-certifikatet används för att autentisera en klient eller tjänst använder Windows Communication Foundation (WCF) som standard Windows-certifikatarkivet och Krypto-API:et för att verifiera certifikatet och för att säkerställa att det är betrott. Ibland räcker inte den inbyggda certifikatverifieringsfunktionen och måste ändras. WCF är ett enkelt sätt att ändra valideringslogik genom att tillåta användare att lägga till en anpassad certifikatverifiering. Om en anpassad certifikatverifierare har angetts använder WCF inte den inbyggda certifikatverifieringslogik utan förlitar sig på den anpassade validatorn i stället.

Förfaranden

Skapa en anpassad certifikatverifierare

  1. Definiera en ny klass som härletts från X509CertificateValidator.

  2. Implementera den abstrakta Validate metoden. Certifikatet som måste verifieras skickas som ett argument till metoden. Om det skickade certifikatet inte är giltigt enligt valideringslogik genererar den här metoden en SecurityTokenValidationException. Om certifikatet är giltigt återgår metoden till anroparen.

    Kommentar

    Om du vill returnera autentiseringsfel tillbaka till klienten genererar du en FaultException i Validate -metoden.

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

Så här anger du en anpassad certifikatverifierare i tjänstkonfigurationen

  1. Lägg till ett beteendeelement> och en <serviceBehaviors> till elementet <system.serviceModel>.<

  2. Lägg till ett <beteende> och ange name attributet till ett lämpligt värde.

  3. Lägg till en serviceCredentials> i elementet<behavior>.<

  4. Lägg till ett <clientCertificate> element i elementet <serviceCredentials> .

  5. Lägg till en <autentisering> i elementet <clientCertificate> .

  6. customCertificateValidatorType Ange attributet till validatortypen. I följande exempel anges attributet till namnområdet och namnet på typen.

  7. Ange attributet certificateValidationMode till 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>  
    

Så här anger du en anpassad certifikatverifierare med hjälp av konfigurationen på klienten

  1. Lägg till ett beteendeelement> och en <serviceBehaviors> till elementet <system.serviceModel>.<

  2. Lägg till ett endpointBehaviors-element>.<

  3. Lägg till ett <behavior> element och ange name attributet till ett lämpligt värde.

  4. Lägg till ett clientCredentials-element>.<

  5. Lägg till en serviceCertificate>.<

  6. Lägg till en <autentisering> enligt följande exempel.

  7. customCertificateValidatorType Ange attributet till validatortypen.

  8. Ange attributet certificateValidationMode till Custom. I följande exempel anges attributet till namnområdet och namnet på typen.

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

Så här anger du en anpassad certifikatverifierare med hjälp av kod i tjänsten

  1. Ange den anpassade certifikatverifieraren för ClientCertificate egenskapen. Du kan komma åt autentiseringsuppgifterna för tjänsten med hjälp av Credentials egenskapen .

  2. Ange egenskapen CertificateValidationMode till 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")

Ange en anpassad certifikatverifierare med hjälp av kod på klienten

  1. Ange den anpassade certifikatverifieraren med hjälp av CustomCertificateValidator egenskapen . Du kan komma åt klientens autentiseringsuppgifter med hjälp av Credentials egenskapen . (Klientklassen som genereras av ServiceModel Metadata Utility Tool (Svcutil.exe) härleds alltid från ClientBase<TChannel> klassen.)

  2. Ange egenskapen CertificateValidationMode till Custom.

Exempel

beskrivning

Följande exempel visar en implementering av en anpassad certifikatverifierare och dess användning på tjänsten.

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

Se även