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
Zdefiniuj nową klasę pochodzącą z klasy X509CertificateValidator.
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
Dodaj element behaviors> i <serviceBehaviors> do <elementu system.serviceModel>.<
<Dodaj zachowanie> i ustaw
name
atrybut na odpowiednią wartość.Dodaj element serviceCredentials>
<behavior>
.<<clientCertificate>
Dodaj element do<serviceCredentials>
elementu .<Dodaj uwierzytelnianie> do
<clientCertificate>
elementu .customCertificateValidatorType
Ustaw atrybut na typ modułu sprawdzania poprawności. Poniższy przykład ustawia atrybut na przestrzeń nazw i nazwę typu.certificateValidationMode
Ustaw atrybut naCustom
.<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
Dodaj element behaviors> i <serviceBehaviors> do <elementu system.serviceModel>.<
<behavior>
Dodaj element i ustawname
atrybut na odpowiednią wartość.Dodaj usługęCertyfikat><.
<Dodaj uwierzytelnianie>, jak pokazano w poniższym przykładzie.
customCertificateValidatorType
Ustaw atrybut na typ modułu sprawdzania poprawności.certificateValidationMode
Ustaw atrybut naCustom
. 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
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 .
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
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 .
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