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.
L’exemple TrustedFacade montre comment transmettre les informations d’identité de l’appelant d’un service à un autre à l’aide de l’infrastructure de sécurité WINDOWS Communication Foundation (WCF).
Il s’agit d’un modèle de conception courant pour exposer les fonctionnalités fournies par un service au réseau public à l’aide d’un service de façade. Le service de façade réside généralement dans le réseau de périmètre (également appelé DMZ, zone démilitarisée et sous-réseau filtré) et communique avec un service principal qui implémente la logique métier et a accès aux données internes. Le canal de communication entre le service de façade et le service principal passe par un pare-feu et est généralement limité à un seul usage.
Cet exemple se compose des composants suivants :
Client de calculatrice
Service de façade de calculatrice
Service principal de calculatrice
Le service de façade est chargé de valider la demande et d'authentifier l'appelant. Une fois l’authentification et la validation réussies, elle transfère la requête au service principal à l’aide du canal de communication contrôlé du réseau de périmètre vers le réseau interne. Dans le cadre de la demande transférée, le service de façade inclut des informations sur l’identité de l’appelant afin que le service principal puisse utiliser ces informations dans son traitement. L’identité de l’appelant est transmise à l’aide d’un Username
jeton de sécurité à l’intérieur de l’en-tête du message Security
. L’exemple utilise l’infrastructure de sécurité WCF pour transmettre et extraire ces informations de l’en-tête Security
.
Importante
Le service back-end fait confiance au service de façade pour authentifier l’appelant. En raison de cela, le service back-end n’authentifie pas à nouveau l’appelant ; il utilise les informations d’identité fournies par le service de façade dans la demande transférée. En raison de cette relation de confiance, le service back-end doit authentifier le service de façade pour s’assurer que le message transféré provient d’une source approuvée, en l’occurrence le service de façade.
Implémentation
Il existe deux chemins de communication dans cet exemple. Tout d’abord, entre le client et le service de façade, le second est entre le service de façade et le service principal.
Chemin de communication entre le client et le service de façade
La voie de communication entre le client et le service de façade utilise wsHttpBinding
avec un type d'informations d'identification de client UserName
. Cela signifie que le client utilise le nom d’utilisateur et le mot de passe pour s’authentifier auprès du service de façade et que le service de façade utilise le certificat X.509 pour s’authentifier auprès du client. La configuration de liaison ressemble à l’exemple suivant.
<bindings>
<wsHttpBinding>
<binding name="Binding1">
<security mode="Message">
<message clientCredentialType="UserName"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
Le service de façade authentifie l'appelant à l'aide de l'implémentation UserNamePasswordValidator
personnalisée. À des fins de démonstration, l’authentification garantit uniquement que le nom d’utilisateur de l’appelant correspond au mot de passe présenté. Dans le monde réel, l’utilisateur est probablement authentifié à l’aide d’Active Directory ou d’un fournisseur d’appartenances personnalisé ASP.NET. L’implémentation du validateur réside dans le FacadeService.cs
fichier.
public class MyUserNamePasswordValidator : UserNamePasswordValidator
{
public override void Validate(string userName, string password)
{
// check that username matches password
if (null == userName || userName != password)
{
Console.WriteLine("Invalid username or password");
throw new SecurityTokenValidationException(
"Invalid username or password");
}
}
}
Le validateur personnalisé est configuré pour être utilisé à l'intérieur du comportement serviceCredentials
, dans le fichier de configuration du service de façade. Ce comportement est également utilisé pour configurer le certificat X.509 du service.
<behaviors>
<serviceBehaviors>
<behavior name="FacadeServiceBehavior">
<!--The serviceCredentials behavior allows you to define -->
<!--a service certificate. -->
<!--A service certificate is used by the service to -->
<!--authenticate itself to its clients and to provide -->
<!--message protection. -->
<!--This configuration references the "localhost" -->
<!--certificate installed during the setup instructions. -->
<serviceCredentials>
<serviceCertificate
findValue="localhost"
storeLocation="LocalMachine"
storeName="My"
x509FindType="FindBySubjectName" />
<userNameAuthentication userNamePasswordValidationMode="Custom"
customUserNamePasswordValidatorType=
"Microsoft.ServiceModel.Samples.MyUserNamePasswordValidator,
FacadeService"/>
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
Chemin de communication entre le service de façade et le service principal
La voie de communication entre le service de façade et le service principal utilise une liaison customBinding
qui se compose de plusieurs éléments de liaison. Cette liaison remplit deux fonctions. Il authentifie le service de façade et le service back-end pour s’assurer que la communication est sécurisée et provient d’une source approuvée. En outre, il transmet également l’identité de l’appelant initial à l’intérieur du Username
jeton de sécurité. Dans ce cas, seul le nom d’utilisateur de l’appelant initial est transmis au service principal, le mot de passe n’est pas inclus dans le message. Cela est dû au fait que le service backend fait confiance au service façade pour authentifier l’appelant avant de lui transférer la demande. Étant donné que le service de façade s’authentifie auprès du service principal, le service principal peut approuver les informations contenues dans la demande transférée.
Voici la configuration de liaison pour ce chemin de communication.
<bindings>
<customBinding>
<binding name="ClientBinding">
<security authenticationMode="UserNameOverTransport"/>
<windowsStreamSecurity/>
<tcpTransport/>
</binding>
</customBinding>
</bindings>
L’élément de liaison <security> se charge de transmettre et d’extraire le nom d’utilisateur de l’appelant initial. WindowsStreamSecurity<> et <tcpTransport> s’occupent de l’authentification des services de façade et de back-end et de la protection des messages.
Pour transférer la requête, l’implémentation du service de façade doit fournir le nom d’utilisateur de l’appelant initial afin que l’infrastructure de sécurité WCF puisse le placer dans le message transféré. Le nom d’utilisateur initial de l’appelant est fourni dans l’implémentation du service de façade en le définissant dans la propriété sur l’instance ClientCredentials
de proxy client utilisée par le service de façade pour communiquer avec le service principal.
Le code suivant montre comment la méthode GetCallerIdentity
est implémentée sur le service de façade. D’autres méthodes utilisent le même modèle.
public string GetCallerIdentity()
{
CalculatorClient client = new CalculatorClient();
client.ClientCredentials.UserName.UserName = ServiceSecurityContext.Current.PrimaryIdentity.Name;
string result = client.GetCallerIdentity();
client.Close();
return result;
}
Comme indiqué dans le code précédent, le mot de passe n’est pas défini sur la ClientCredentials
propriété, seul le nom d’utilisateur est défini. L’infrastructure de sécurité WCF crée un jeton de sécurité de nom d’utilisateur sans mot de passe dans ce cas, ce qui est exactement ce qui est requis dans ce scénario.
Sur le service principal, les informations contenues dans le jeton de sécurité du nom d’utilisateur doivent être authentifiées. Par défaut, la sécurité WCF tente de mapper l’utilisateur à un compte Windows à l’aide du mot de passe fourni. Dans ce cas, il n’existe aucun mot de passe fourni et le service principal n’est pas requis pour authentifier le nom d’utilisateur, car l’authentification a déjà été effectuée par le service de façade. Pour implémenter cette fonctionnalité dans WCF, une fonctionnalité personnalisée UserNamePasswordValidator
est fournie qui applique uniquement qu’un nom d’utilisateur est spécifié dans le jeton et n’effectue aucune authentification supplémentaire.
public class MyUserNamePasswordValidator : UserNamePasswordValidator
{
public override void Validate(string userName, string password)
{
// Ignore the password because it is empty,
// we trust the facade service to authenticate the client.
// Accept the username information here so that the
// application gets access to it.
if (null == userName)
{
Console.WriteLine("Invalid username");
throw new
SecurityTokenValidationException("Invalid username");
}
}
}
Le validateur personnalisé est configuré pour être utilisé à l'intérieur du comportement serviceCredentials
, dans le fichier de configuration du service de façade.
<behaviors>
<serviceBehaviors>
<behavior name="BackendServiceBehavior">
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="Custom"
customUserNamePasswordValidatorType=
"Microsoft.ServiceModel.Samples.MyUserNamePasswordValidator,
BackendService"/>
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
Pour extraire les informations de nom d’utilisateur et les informations sur le compte de service de façade approuvé, l’implémentation du service principal utilise la ServiceSecurityContext
classe. Le code suivant montre comment la GetCallerIdentity
méthode est implémentée.
public string GetCallerIdentity()
{
// Facade service is authenticated using Windows authentication.
//Its identity is accessible.
// On ServiceSecurityContext.Current.WindowsIdentity.
string facadeServiceIdentityName =
ServiceSecurityContext.Current.WindowsIdentity.Name;
// The client name is transmitted using Username authentication on
//the message level without the password
// using a supporting encrypted UserNameToken.
// Claims extracted from this supporting token are available in
// ServiceSecurityContext.Current.AuthorizationContext.ClaimSets
// collection.
string clientName = null;
foreach (ClaimSet claimSet in
ServiceSecurityContext.Current.AuthorizationContext.ClaimSets)
{
foreach (Claim claim in claimSet)
{
if (claim.ClaimType == ClaimTypes.Name &&
claim.Right == Rights.Identity)
{
clientName = (string)claim.Resource;
break;
}
}
}
if (clientName == null)
{
// In case there was no UserNameToken attached to the request.
// In the real world implementation the service should reject
// this request.
return "Anonymous caller via " + facadeServiceIdentityName;
}
return clientName + " via " + facadeServiceIdentityName;
}
Les informations relatives au compte du service de façade sont extraites à l'aide de la propriété ServiceSecurityContext.Current.WindowsIdentity
. Pour accéder aux informations relatives à l’appelant initial, le service principal utilise la ServiceSecurityContext.Current.AuthorizationContext.ClaimSets
propriété. Le service recherche une revendication Identity
ayant le type Name
. Cette revendication est générée automatiquement par l’infrastructure de sécurité WCF à partir des informations contenues dans le Username
jeton de sécurité.
Exécution de l’exemple
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. Appuyez sur Entrée dans la fenêtre du client pour arrêter le client. Vous pouvez appuyer sur Entrée dans les fenêtres de la console de service du frontend et du backend pour arrêter les services.
Username authentication required.
Provide a valid machine or domain ac
Enter username:
user
Enter password:
****
user via MyMachine\testaccount
Add(100,15.99) = 115.99
Subtract(145,76.54) = 68.46
Multiply(9,81.25) = 731.25
Divide(22,7) = 3.14285714285714
Press <ENTER> to terminate client.
Le fichier batch Setup.bat inclus dans l’exemple de scénario de façade approuvée vous permet de configurer le serveur avec un certificat approprié pour exécuter le service de façade qui nécessite une sécurité basée sur des certificats pour s’authentifier auprès du client. Pour plus d’informations, consultez la procédure de configuration à la fin de cette rubrique.
Voici une brève vue d’ensemble des différentes sections des fichiers batch.
Création du certificat de serveur.
Les lignes suivantes du fichier batch Setup.bat créent le certificat de serveur à utiliser.
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
La
%SERVER_NAME%
variable spécifie le nom du serveur : la valeur par défaut est localhost. Le certificat est stocké dans le magasin LocalMachine.Installation du certificat du service de façade dans le magasin de certificats approuvés du client.
La ligne suivante copie le certificat du service de façade 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 client. Si vous disposez déjà d’un certificat rooté dans un certificat racine approuvé par le 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
Pour configurer, générer et exécuter l’exemple
Assurez-vous d’avoir effectué la Procédure d’installation unique pour les exemples Windows Communication Foundation.
Pour générer l’édition C# ou Visual Basic .NET de la solution, conformez-vous aux instructions figurant dans Building the Windows Communication Foundation Samples.
Pour exécuter l’exemple sur le même ordinateur
Vérifiez que le chemin inclut le dossier où se trouve Makecert.exe.
Exécutez Setup.bat à partir de l’exemple de dossier d’installation. Cela installe tous les certificats requis pour l’exécution de l’exemple.
Lancez le BackendService.exe à partir du répertoire \BackendService\bin dans une fenêtre de console distincte
Lancez le FacadeService.exe à partir du répertoire \FaçadeService\bin dans une fenêtre de console distincte
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 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.