Notes
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
Cet exemple montre comment implémenter un validateur de certificat X.509 personnalisé. Cela est utile dans les cas où aucun des modes de validation de certificat X.509 intégrés n’est approprié pour les exigences de l’application. Cet exemple montre un service disposant d’un validateur personnalisé qui accepte des certificats auto-émis. Le client utilise un tel certificat pour s’authentifier auprès du service.
Remarque : Comme tout le monde peut construire un certificat auto-émis, le validateur personnalisé utilisé par le service est moins sécurisé que le comportement par défaut fourni par chainTrust X509CertificateValidationMode. Les implications en matière de sécurité doivent être soigneusement prises en compte avant d’utiliser cette logique de validation dans le code de production.
En résumé, cet exemple montre comment :
Le client peut être authentifié à l’aide d’un certificat X.509.
Le serveur valide les informations d’identification du client par rapport à un X509CertificateValidator personnalisé.
Le serveur est authentifié à l’aide du certificat X.509 du serveur.
Le service expose un point de terminaison unique pour communiquer avec le service, défini à l’aide du fichier de configuration App.config. Le point de terminaison se compose d’une adresse, d’une liaison et d’un contrat. La liaison est configurée avec une norme wsHttpBinding
qui utilise par défaut WSSecurity
et l'authentification par certificat client. Le comportement du service spécifie le mode personnalisé pour valider les certificats X.509 clients, ainsi que le type de la classe validateur. Le comportement spécifie également le certificat de serveur à l’aide de l’élément serviceCertificate. Le certificat de serveur doit contenir la même valeur pour SubjectName
que la valeur de findValue
dans le <serviceCertificate>.
<system.serviceModel>
<services>
<service name="Microsoft.ServiceModel.Samples.CalculatorService"
behaviorConfiguration="CalculatorServiceBehavior">
<!-- use host/baseAddresses to configure base address -->
<!-- provided by host -->
<host>
<baseAddresses>
<add baseAddress =
"http://localhost:8001/servicemodelsamples/service" />
</baseAddresses>
</host>
<!-- use base address specified above, provide one endpoint -->
<endpoint address="certificate"
binding="wsHttpBinding"
bindingConfiguration="Binding"
contract="Microsoft.ServiceModel.Samples.ICalculator" />
</service>
</services>
<bindings>
<wsHttpBinding>
<!-- X509 certificate binding -->
<binding name="Binding">
<security mode="Message">
<message clientCredentialType="Certificate" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="CalculatorServiceBehavior">
<serviceDebug includeExceptionDetailInFaults ="true"/>
<serviceCredentials>
<!-- The serviceCredentials behavior allows one -->
<!-- to specify authentication constraints on -->
<!-- client certificates. -->
<clientCertificate>
<!-- Setting the certificateValidationMode to -->
<!-- Custom means that if the custom -->
<!-- X509CertificateValidator does NOT throw -->
<!-- an exception, then the provided certificate -->
<!-- will be trusted without performing any -->
<!-- validation beyond that performed by the custom -->
<!-- validator. The security implications of this -->
<!-- setting should be carefully considered before -->
<!-- using Custom in production code. -->
<authentication
certificateValidationMode="Custom"
customCertificateValidatorType =
"Microsoft.ServiceModel.Samples.CustomX509CertificateValidator, service" />
</clientCertificate>
<!-- The serviceCredentials behavior allows one to -->
<!-- define a service certificate. -->
<!-- A service certificate is used by a client to -->
<!-- authenticate the service and provide message -->
<!-- protection. This configuration references the -->
<!-- "localhost" certificate installed during the setup -->
<!-- instructions. -->
<serviceCertificate findValue="localhost"
storeLocation="LocalMachine"
storeName="My" x509FindType="FindBySubjectName" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
La configuration du point de terminaison client se compose d’un nom de configuration, d’une adresse absolue pour le point de terminaison de service, de la liaison et du contrat. La liaison cliente est configurée avec le mode et le message clientCredentialType
appropriés.
<system.serviceModel>
<client>
<!-- X509 certificate based endpoint -->
<endpoint name="Certificate"
address=
"http://localhost:8001/servicemodelsamples/service/certificate"
binding="wsHttpBinding"
bindingConfiguration="Binding"
behaviorConfiguration="ClientCertificateBehavior"
contract="Microsoft.ServiceModel.Samples.ICalculator">
</endpoint>
</client>
<bindings>
<wsHttpBinding>
<!-- X509 certificate binding -->
<binding name="Binding">
<security mode="Message">
<message clientCredentialType="Certificate" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="ClientCertificateBehavior">
<clientCredentials>
<serviceCertificate>
<!-- Setting the certificateValidationMode to -->
<!-- PeerOrChainTrust means that if the certificate -->
<!-- is in the user's Trusted People store, then it -->
<!-- is trusted without performing a validation of -->
<!-- the certificate's issuer chain. -->
<!-- This setting is used here for convenience so -->
<!-- that the sample can be run without having to -->
<!-- have certificates issued by a certification -->
<!-- authority (CA). This setting is less secure -->
<!-- than the default, ChainTrust. The security -->
<!-- implications of this setting should be -->
<!-- carefully considered before using -->
<!-- PeerOrChainTrust in production code.-->
<authentication
certificateValidationMode="PeerOrChainTrust" />
</serviceCertificate>
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
L’implémentation du client définit le certificat client à utiliser.
// Create a client with Certificate endpoint configuration
CalculatorClient client = new CalculatorClient("Certificate");
try
{
client.ClientCredentials.ClientCertificate.SetCertificate(StoreLocation.CurrentUser, StoreName.My, X509FindType.FindBySubjectName, "test1");
// Call the Add service operation.
double value1 = 100.00D;
double value2 = 15.99D;
double result = client.Add(value1, value2);
Console.WriteLine("Add({0},{1}) = {2}", value1, value2, result);
// Call the Subtract service operation.
value1 = 145.00D;
value2 = 76.54D;
result = client.Subtract(value1, value2);
Console.WriteLine("Subtract({0},{1}) = {2}", value1, value2, result);
// Call the Multiply service operation.
value1 = 9.00D;
value2 = 81.25D;
result = client.Multiply(value1, value2);
Console.WriteLine("Multiply({0},{1}) = {2}", value1, value2, result);
// Call the Divide service operation.
value1 = 22.00D;
value2 = 7.00D;
result = client.Divide(value1, value2);
Console.WriteLine("Divide({0},{1}) = {2}", value1, value2, result);
client.Close();
}
catch (TimeoutException e)
{
Console.WriteLine("Call timed out : {0}", e.Message);
client.Abort();
}
catch (CommunicationException e)
{
Console.WriteLine("Call failed : {0}", e.Message);
client.Abort();
}
catch (Exception e)
{
Console.WriteLine("Call failed : {0}", e.Message);
client.Abort();
}
Cet exemple utilise un X509CertificateValidator personnalisé pour valider les certificats. L’exemple implémente CustomX509CertificateValidator, dérivé de X509CertificateValidator. Pour plus d’informations, consultez la documentation au sujet de X509CertificateValidator. Cet exemple de validateur personnalisé particulier implémente la méthode Validate pour accepter tout certificat X.509 auto-émis comme indiqué dans le code suivant.
public class CustomX509CertificateValidator : X509CertificateValidator
{
public override void Validate ( X509Certificate2 certificate )
{
// Only accept self-issued certificates
if (certificate.Subject != certificate.Issuer)
throw new Exception("Certificate is not self-issued");
}
}
Une fois le validateur implémenté dans le code de service, l’hôte de service doit être informé de l’instance de validateur à utiliser. Pour ce faire, utilisez le code suivant.
serviceHost.Credentials.ClientCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.Custom;
serviceHost.Credentials.ClientCertificate.Authentication.CustomCertificateValidator = new CustomX509CertificateValidator();
Ou vous pouvez faire la même chose dans la configuration comme suit.
<behaviors>
<serviceBehaviors>
<behavior name="CalculatorServiceBehavior">
...
<serviceCredentials>
<!--The serviceCredentials behavior allows one to specify -->
<!--authentication constraints on client certificates.-->
<clientCertificate>
<!-- Setting the certificateValidationMode to Custom means -->
<!--that if the custom X509CertificateValidator does NOT -->
<!--throw an exception, then the provided certificate will -->
<!--be trusted without performing any validation beyond that -->
<!--performed by the custom validator. The security -->
<!--implications of this setting should be carefully -->
<!--considered before using Custom in production code. -->
<authentication certificateValidationMode="Custom"
customCertificateValidatorType =
"Microsoft.ServiceModel.Samples. CustomX509CertificateValidator, service" />
</clientCertificate>
</serviceCredentials>
...
</behavior>
</serviceBehaviors>
</behaviors>
Lorsque vous exécutez l’exemple, les demandes et réponses de l’opération s’affichent dans la fenêtre de la console cliente. Le client doit appeler toutes les méthodes avec succès. Appuyez sur Entrée dans la fenêtre du client pour arrêter le client.
Configurer le fichier Batch
Le fichier batch Setup.bat inclus dans cet exemple vous permet de configurer le serveur avec des certificats pertinents pour exécuter une application auto-hébergée qui nécessite une sécurité basée sur les certificats du serveur. Ce fichier de commandes doit être modifié pour fonctionner sur plusieurs ordinateurs ou pour fonctionner dans un cas non hébergé.
Voici une brève vue d’ensemble des différentes sections des fichiers batch afin qu’ils puissent être modifiés pour s’exécuter dans la configuration appropriée :
Création du certificat de serveur :
Les lignes suivantes du fichier batch Setup.bat créent le certificat de serveur à utiliser. La variable %SERVER_NAME% spécifie le nom du serveur. Modifiez cette variable pour spécifier votre propre nom de serveur. La valeur par défaut est localhost.
echo ************ echo Server cert setup starting echo %SERVER_NAME% echo ************ echo making server cert echo ************ makecert.exe -sr LocalMachine -ss MY -a sha1 -n CN=%SERVER_NAME% -sky exchange -pe
Installation du certificat de serveur dans le magasin de certificats approuvé du client :
Les lignes suivantes du fichier batch Setup.bat copient le certificat de serveur dans le répertoire des contacts de confiance du client. Cette étape est requise, car les certificats générés par Makecert.exe ne sont pas implicitement approuvés par le système client. Si vous disposez déjà d’un certificat rooté dans un certificat racine approuvé client( par exemple, un certificat émis par Microsoft), cette étape de remplissage du magasin de certificats client avec le certificat de serveur n’est pas nécessaire.
certmgr.exe -add -r LocalMachine -s My -c -n %SERVER_NAME% -r CurrentUser -s TrustedPeople
Création du certificat client :
Les lignes suivantes du fichier batch Setup.bat créent le certificat client à utiliser. La variable %USER_NAME% spécifie le nom du client. Cette valeur est définie sur « test1 », car il s’agit du nom que le code client recherche. Si vous modifiez la valeur de %USER_NAME% vous devez modifier la valeur correspondante dans le fichier source Client.cs et reconstruire le client.
Le certificat est stocké dans le magasin My (Personnel) sous l’emplacement du magasin CurrentUser.
echo ************ echo Client cert setup starting echo %USER_NAME% echo ************ echo making client cert echo ************ makecert.exe -sr CurrentUser -ss MY -a sha1 -n CN=%USER_NAME% -sky exchange -pe
Installation du certificat client dans le magasin de certificats approuvé du serveur :
Les lignes suivantes du fichier de commandes Setup.bat copient le certificat client dans le magasin de personnes de confiance du client. Cette étape est requise, car les certificats générés par Makecert.exe ne sont pas implicitement approuvés par le système serveur. Si vous disposez déjà d’un certificat rooté dans un certificat racine approuvé( par exemple, un certificat émis par Microsoft), cette étape de remplissage du magasin de certificats serveur avec le certificat client n’est pas nécessaire.
certmgr.exe -add -r CurrentUser -s My -c -n %USER_NAME% -r LocalMachine -s TrustedPeople
Pour configurer et compiler l’exemple
Pour générer la solution, suivez les instructions de Création des exemples Windows Communication Foundation.
Pour exécuter l’exemple dans une configuration à ordinateur unique ou inter-ordinateur, utilisez les instructions suivantes.
Pour exécuter l’exemple sur le même ordinateur
Exécutez Setup.bat à partir de l’exemple de dossier d’installation à l’intérieur d’une invite de commandes Visual Studio ouverte avec des privilèges d’administrateur. Cela installe tous les certificats requis pour l’exécution de l’exemple.
Importante
Le fichier de commandes Setup.bat est conçu pour être exécuté à partir d'une fenêtre de commande Visual Studio. La variable d’environnement PATH définie dans l’invite de commandes Visual Studio pointe vers le répertoire qui contient des exécutables requis par le script Setup.bat.
Lancez Service.exe à partir de service\bin.
Lancez Client.exe à partir de \client\bin. L’activité du client s’affiche sur l’application console cliente.
Si le client et le service ne sont pas en mesure de communiquer, consultez Conseils de résolution des problèmes pour les exemples WCF.
Pour exécuter l’exemple sur différents ordinateurs
Créez un répertoire sur l’ordinateur de service.
Copiez les fichiers de programme de service de \service\bin dans le répertoire virtuel sur l’ordinateur de service. Copiez également les fichiers Setup.bat, Cleanup.bat, GetComputerName.vbs et ImportClientCert.bat sur l’ordinateur de service.
Créez un répertoire sur l’ordinateur client pour les fichiers binaires clients.
Copiez les fichiers de programme client dans le répertoire client sur l’ordinateur client. Copiez également les fichiers Setup.bat, Cleanup.batet ImportServiceCert.bat sur le client.
Sur le serveur, exécutez
setup.bat service
dans une Invite de commandes développeur pour Visual Studio ouverte avec des privilèges d’administrateur. L’exécution desetup.bat
avec l’argumentservice
crée un certificat de service avec le nom de domaine complet de l’ordinateur et exporte le certificat de service vers un fichier nommé Service.cer.Modifiez Service.exe.config pour refléter le nouveau nom de certificat (dans l’attribut
findValue
du <serviceCertificate>) qui est le même que le nom de domaine complet de l’ordinateur. Modifiez également le nom de l’ordinateur dans l’élément <service>/<baseAddresses> de localhost en nom complet de votre ordinateur de service.Copiez le fichier Service.cer du répertoire de service vers le répertoire client sur l’ordinateur client.
Sur le client, exécutez
setup.bat client
dans une Invite de commandes développeur pour Visual Studio ouverte avec des privilèges d’administrateur. L’exécution desetup.bat
avec l’argumentclient
crée un certificat client nommé client.com et exporte le certificat client vers un fichier nommé Client.cer.Dans le fichier Client.exe.config sur l’ordinateur client, modifiez la valeur d’adresse du point de terminaison pour qu’il corresponde à la nouvelle adresse de votre service. Pour ce faire, remplacez localhost par le nom de domaine complet du serveur.
Copiez le fichier Client.cer du répertoire client vers le répertoire de service sur le serveur.
Sur le client, exécutez ImportServiceCert.bat dans une Invite de commandes développeur pour Visual Studio ouverte avec des privilèges d’administrateur. Cela importe le certificat de service à partir du fichier Service.cer dans le magasin CurrentUser - TrustedPeople.
Sur le serveur, exécutez ImportClientCert.bat dans une invite de commandes de développement pour Visual Studio ouverte avec des privilèges d’administrateur. Cela importe le certificat client à partir du fichier Client.cer dans le magasin LocalMachine - TrustedPeople.
Sur l’ordinateur serveur, lancez Service.exe à partir de la fenêtre d’invite de commandes.
Sur l’ordinateur client, lancez Client.exe à partir d’une fenêtre d’invite de commandes. Si le client et le service ne sont pas en mesure de communiquer, consultez Conseils de résolution des problèmes pour les exemples WCF.
Pour nettoyer après le test
- Exécutez Cleanup.bat dans le dossier d’exemples une fois que vous avez terminé d’exécuter l’exemple. Cela supprime le serveur et les certificats clients du magasin de certificats.
Remarque
Ce script ne supprime pas les certificats de service sur un client lors de l’exécution de cet exemple sur les ordinateurs. Si vous avez exécuté des exemples Windows Communication Foundation (WCF) qui utilisent des certificats sur des ordinateurs, veillez à effacer les certificats de service installés dans le magasin CurrentUser - TrustedPeople. Pour ce faire, utilisez la commande suivante : certmgr -del -r CurrentUser -s TrustedPeople -c -n <Fully Qualified Server Machine Name>
Par exemple : certmgr -del -r CurrentUser -s TrustedPeople -c -n server1.contoso.com
.