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
Definieer een nieuwe klasse die is afgeleid van X509CertificateValidator.
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
Voeg een gedragselement> en een <serviceBehaviors> toe aan het <element system.serviceModel>.<
Voeg een <gedrag> toe en stel het
name
kenmerk in op een geschikte waarde.Voeg een <serviceCredentials> toe aan het
<behavior>
element.Voeg een
<clientCertificate>
element toe aan het<serviceCredentials>
element.Voeg een <verificatie> toe aan het
<clientCertificate>
element.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.Stel het
certificateValidationMode
kenmerk in opCustom
.<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
Voeg een gedragselement> en een <serviceBehaviors> toe aan het <element system.serviceModel>.<
Voeg een <endpointBehaviors-element> toe.
Voeg een
<behavior>
element toe en stel hetname
kenmerk in op een juiste waarde.Voeg een <clientCredentials-element> toe.
Voeg een <serviceCertificate> toe.
Voeg een <verificatie> toe, zoals wordt weergegeven in het volgende voorbeeld.
Stel het
customCertificateValidatorType
kenmerk in op het validatietype.Stel het
certificateValidationMode
kenmerk in opCustom
. 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
Geef de aangepaste certificaatvalidator op de ClientCertificate eigenschap op. U kunt de servicereferenties openen met behulp van de Credentials eigenschap.
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
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.)
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