Procédure pas à pas : création d’informations d’identification de client et de service personnalisées
Cette rubrique indique comment implémenter des informations d'identification de client et de service personnalisées et comment les utiliser à partir du code d'application.
Classes d'extensibilité d'informations d'identification
Les classes ClientCredentials et ServiceCredentials sont les principaux points d’entrée de l’extensibilité de sécurité Windows Communication Foundation (WCF). Ces classes d'informations d'identification fournissent les API qui permettent au code d'application de définir des informations d'identification et de convertir les types d'informations d'identification en jetons de sécurité. (Les jetons de sécurité sont le formulaire utilisé pour transmettre des informations d’identification dans les messages SOAP.) Les responsabilités de ces classes d’informations d’identification peuvent être divisées en deux domaines :
Fournir les API pour que les applications définissent des informations d'identification.
S'exécuter en tant que fabrique pour les implémentations SecurityTokenManager.
Les implémentations par défaut fournies dans WCF prennent en charge les types d'informations d'identification fournis par le système et créent un gestionnaire de jetons de sécurité capable de gérer ces types d'informations d'identification.
Raisons de la personnalisation
La personnalisation des classes d'informations d'identification de service ou de client peut se justifier pour plusieurs raisons. La plus importante est la nécessité de modifier le comportement de sécurité WCF par défaut concernant la gestion des types d’informations d’identification fournis par le système, en particulier pour les motifs suivants :
Modifications qu'il n'est pas possible d'effectuer à l'aide d'autres points d'extensibilité.
Ajout de nouveaux types d'informations d'identification.
Ajout de nouveaux types de jetons de sécurité personnalisés.
Cette rubrique décrit comment implémenter des informations d'identification de client et de service personnalisées et comment les utiliser à partir du code d'application.
Première étape
La création d'une classe d'informations d'identification personnalisée n'est que la première étape, car la personnalisation des informations d'identification a pour objectif de modifier le comportement WCF concernant la fourniture, la sérialisation de jeton de sécurité ou l'authentification des informations d'identification. D'autres rubriques de cette section décrivent comment créer des sérialiseurs et authentificateurs personnalisés. À cet égard, la création de la classe d'informations d'identification personnalisées constitue la première rubrique. Les actions suivantes (création de sérialiseurs et authentificateurs personnalisés) peuvent être effectuées uniquement après la création d'informations d'identification personnalisées. Les autres rubriques basées sur celles-ci sont les suivantes :
Procédure : créer un fournisseur de jetons de sécurité personnalisé
Procédure : créer un authentificateur de jetons de sécurité personnalisé
Procédures
Pour implémenter des informations d'identification de client personnalisées
Définissez une nouvelle classe dérivée de la classe ClientCredentials.
facultatif. Ajoutez de nouvelles propriétés ou méthodes pour les nouveaux types d'informations d'identification. Si vous n'ajoutez pas de nouveau type d'informations d'identification, ignorez cette étape. L'exemple suivant ajoute une propriété
CreditCardNumber
.Remplacez la méthode CreateSecurityTokenManager . Cette méthode est automatiquement appelée par l'infrastructure de sécurité WCF lors de l'utilisation des informations d'identification de client personnalisées. Cette méthode est chargée de créer et de retourner une instance d'une implémentation de la classe SecurityTokenManager.
Important
Il est important de noter que la méthode CreateSecurityTokenManager est remplacée pour créer un gestionnaire de jetons de sécurité personnalisé. Le gestionnaire de jetons de sécurité, dérivé de ClientCredentialsSecurityTokenManager, doit retourner un fournisseur de jetons de sécurité personnalisé, dérivé de SecurityTokenProvider, pour créer le jeton de sécurité réel. Si vous ne suivez pas ce modèle pour créer des jetons de sécurité, votre application peut ne pas fonctionner correctement lorsque des objets ChannelFactory sont mis en cache (comportement par défaut des proxys clients WCF), ce qui peut éventuellement provoquer une attaque par élévation de privilège. L'objet personnalisé d'informations d'identification est mis en cache dans le cadre de ChannelFactory. Toutefois, le SecurityTokenManager personnalisé est créé à chaque appel, ce qui limite la menace de sécurité dès l'instant où la logique de création de jeton est placée dans SecurityTokenManager.
Remplacez la méthode CloneCore .
public class MyClientCredentials : ClientCredentials { string creditCardNumber; public MyClientCredentials() { // Perform client credentials initialization. } protected MyClientCredentials(MyClientCredentials other) : base(other) { // Clone fields defined in this class. this.creditCardNumber = other.creditCardNumber; } public string CreditCardNumber { get { return this.creditCardNumber; } set { if (value == null) { throw new ArgumentNullException("value"); } this.creditCardNumber = value; } } public override SecurityTokenManager CreateSecurityTokenManager() { // Return your implementation of the SecurityTokenManager. return new MyClientCredentialsSecurityTokenManager(this); } protected override ClientCredentials CloneCore() { // Implement the cloning functionality. return new MyClientCredentials(this); } }
Public Class MyClientCredentials Inherits ClientCredentials Private creditCardNumberValue As String Public Sub New() End Sub ' Perform client credentials initialization. Protected Sub New(ByVal other As MyClientCredentials) MyBase.New(other) ' Clone fields defined in this class. Me.creditCardNumberValue = other.creditCardNumberValue End Sub Public Property CreditCardNumber() As String Get Return Me.creditCardNumberValue End Get Set If value Is Nothing Then Throw New ArgumentNullException("value") End If Me.creditCardNumberValue = value End Set End Property Public Overrides Function CreateSecurityTokenManager() As SecurityTokenManager ' Return your implementation of the SecurityTokenManager. Return New MyClientCredentialsSecurityTokenManager(Me) End Function Protected Overrides Function CloneCore() As ClientCredentials ' Implement the cloning functionality. Return New MyClientCredentials(Me) End Function End Class
Pour implémenter un gestionnaire de jetons de sécurité client personnalisé
Définissez une nouvelle classe dérivée de ClientCredentialsSecurityTokenManager.
facultatif. Substituez la méthode CreateSecurityTokenProvider(SecurityTokenRequirement) si une implémentation SecurityTokenProvider personnalisée doit être créée. Pour plus d’informations sur les fournisseurs de jetons de sécurité personnalisés, consultez Procédure : créer un fournisseur de jetons de sécurité personnalisé.
facultatif. Substituez la méthode CreateSecurityTokenAuthenticator(SecurityTokenRequirement, SecurityTokenResolver) si une implémentation SecurityTokenAuthenticator personnalisée doit être créée. Pour plus d’informations sur les authentificateurs de jeton de sécurité personnalisés, consultez Procédure : créer un authentificateur de jeton de sécurité personnalisé.
facultatif. Substituez la méthode CreateSecurityTokenSerializer si une implémentation SecurityTokenSerializer personnalisée doit être créée. Pour plus d'informations sur les jetons de sécurité personnalisés et les sérialiseurs de jeton de sécurité personnalisés, consultez Procédure : créer un jeton personnalisé.
internal class MyClientCredentialsSecurityTokenManager : ClientCredentialsSecurityTokenManager { MyClientCredentials credentials; public MyClientCredentialsSecurityTokenManager(MyClientCredentials credentials) : base(credentials) { this.credentials = credentials; } public override SecurityTokenProvider CreateSecurityTokenProvider( SecurityTokenRequirement tokenRequirement) { // Return your implementation of the SecurityTokenProvider, if required. // This implementation delegates to the base class. return base.CreateSecurityTokenProvider(tokenRequirement); } public override SecurityTokenAuthenticator CreateSecurityTokenAuthenticator( SecurityTokenRequirement tokenRequirement, out SecurityTokenResolver outOfBandTokenResolver) { // Return your implementation of the SecurityTokenAuthenticator, if required. // This implementation delegates to the base class. return base.CreateSecurityTokenAuthenticator(tokenRequirement, out outOfBandTokenResolver); } public override SecurityTokenSerializer CreateSecurityTokenSerializer(SecurityTokenVersion version) { // Return your implementation of the SecurityTokenSerializer, if required. // This implementation delegates to the base class. return base.CreateSecurityTokenSerializer(version); } }
Friend Class MyClientCredentialsSecurityTokenManager Inherits ClientCredentialsSecurityTokenManager Private credentials As MyClientCredentials Public Sub New(ByVal credentials As MyClientCredentials) MyBase.New(credentials) Me.credentials = credentials End Sub Public Overrides Function CreateSecurityTokenProvider( _ ByVal tokenRequirement As SecurityTokenRequirement) As SecurityTokenProvider ' Return your implementation of the SecurityTokenProvider, if required. ' This implementation delegates to the base class. Return MyBase.CreateSecurityTokenProvider(tokenRequirement) End Function Public Overrides Function CreateSecurityTokenAuthenticator( _ ByVal tokenRequirement As SecurityTokenRequirement, _ ByRef outOfBandTokenResolver As SecurityTokenResolver) As SecurityTokenAuthenticator ' Return your implementation of the SecurityTokenAuthenticator, if required. ' This implementation delegates to the base class. Return MyBase.CreateSecurityTokenAuthenticator(tokenRequirement, outOfBandTokenResolver) End Function Public Overrides Function CreateSecurityTokenSerializer(ByVal version As SecurityTokenVersion) _ As SecurityTokenSerializer ' Return your implementation of the SecurityTokenSerializer, if required. ' This implementation delegates to the base class. Return MyBase.CreateSecurityTokenSerializer(version) End Function End Class
Pour utiliser des informations d'identification de client personnalisées à partir du code de l'application
Créez une instance du client généré qui représente l'interface de service, ou créez une instance de ChannelFactory qui pointe vers un service avec lequel vous souhaitez communiquer.
Supprimez le comportement d’informations d’identification de client fourni par le système de la collection Behaviors, qui est accessible via la propriété Endpoint.
Créez une nouvelle instance d’une classe d’informations d’identification de client personnalisées et ajoutez-la à la collection Behaviors, qui est accessible via la propriété Endpoint.
// Create a client with the client endpoint configuration. CalculatorClient client = new CalculatorClient(); // Remove the ClientCredentials behavior. client.ChannelFactory.Endpoint.Behaviors.Remove<ClientCredentials>(); // Add a custom client credentials instance to the behaviors collection. client.ChannelFactory.Endpoint.Behaviors.Add(new MyClientCredentials());
' Create a client with the client endpoint configuration. Dim client As New CalculatorClient() ' Remove the ClientCredentials behavior. client.ChannelFactory.Endpoint.Behaviors.Remove(Of ClientCredentials)() ' Add a custom client credentials instance to the behaviors collection. client.ChannelFactory.Endpoint.Behaviors.Add(New MyClientCredentials())
La procédure précédente indique comment utiliser les informations d'identification du client à partir du code de l'application. Les informations d'identification WCF peuvent également être configurées en utilisant le fichier de configuration de l'application. L'utilisation de la configuration de l'application est souvent préférable à l'encodage effectué de manière irréversible, car elle permet de modifier les paramètres d'application sans qu'il soit nécessaire de modifier la source, de recompiler et de redéployer.
La procédure suivante décrit comment assurer la prise en charge de la configuration des informations d'identification personnalisées.
Création d'un gestionnaire de configuration pour les informations d'identification de client personnalisées
Définissez une nouvelle classe dérivée de ClientCredentialsElement.
facultatif. Ajoutez des propriétés pour tous les paramètres de configuration supplémentaires que vous souhaitez exposer via la configuration de l'application. L'exemple ci-dessous ajoute une propriété appelée
CreditCardNumber
.Substituez la propriété BehaviorType pour retourner le type de la classe d'informations d'identification de client personnalisées créée avec l'élément de configuration.
Remplacez la méthode CreateBehavior . La méthode est chargée de créer et de retourner une instance de la classe d'informations d'identification personnalisées en fonction des paramètres chargés à partir du fichier de configuration. Appelez la méthode ApplyConfiguration(ClientCredentials) de base à partir de cette méthode pour récupérer les paramètres d'informations d'identification fournis par le système chargés dans votre instance d'informations d'identification de client personnalisées.
facultatif. Si vous avez ajouté des propriétés supplémentaires dans l'étape 2, vous devez substituer la propriété Properties pour enregistrer vos paramètres de configuration supplémentaires afin que l'infrastructure de configuration les reconnaisse. Combinez vos propriétés avec celle de la classe de base afin de permettre la configuration des paramètres fournis par le système via cet élément de configuration d'informations d'identification de client personnalisées.
public class MyClientCredentialsConfigHandler : ClientCredentialsElement { ConfigurationPropertyCollection properties; public override Type BehaviorType { get { return typeof(MyClientCredentials); } } public string CreditCardNumber { get { return (string)base["creditCardNumber"]; } set { if (String.IsNullOrEmpty(value)) { value = String.Empty; } base["creditCardNumber"] = value; } } protected override ConfigurationPropertyCollection Properties { get { if (this.properties == null) { ConfigurationPropertyCollection properties = base.Properties; properties.Add(new ConfigurationProperty( "creditCardNumber", typeof(System.String), string.Empty, null, new StringValidator(0, 32, null), ConfigurationPropertyOptions.None)); this.properties = properties; } return this.properties; } } protected override object CreateBehavior() { MyClientCredentials creds = new MyClientCredentials(); creds.CreditCardNumber = CreditCardNumber; base.ApplyConfiguration(creds); return creds; } }
Public Class MyClientCredentialsConfigHandler Inherits ClientCredentialsElement Private propertiesValue As ConfigurationPropertyCollection Public Overrides ReadOnly Property BehaviorType() As Type Get Return GetType(MyClientCredentials) End Get End Property Public Property CreditCardNumber() As String Get Return CStr(MyBase.Item("creditCardNumber")) End Get Set If String.IsNullOrEmpty(value) Then value = String.Empty End If MyBase.Item("creditCardNumber") = value End Set End Property Protected Overrides ReadOnly Property Properties() As ConfigurationPropertyCollection Get If Me.propertiesValue Is Nothing Then Dim myProperties As ConfigurationPropertyCollection = MyBase.Properties myProperties.Add(New ConfigurationProperty( _ "creditCardNumber", _ GetType(System.String), _ String.Empty, _ Nothing, _ New StringValidator(0, 32, Nothing), _ ConfigurationPropertyOptions.None)) Me.propertiesValue = myProperties End If Return Me.propertiesValue End Get End Property Protected Overrides Function CreateBehavior() As Object Dim creds As New MyClientCredentials() creds.CreditCardNumber = Me.CreditCardNumber MyBase.ApplyConfiguration(creds) Return creds End Function End Class
Lorsque vous disposez de la classe de gestionnaire de configuration, vous pouvez l'intégrer dans l'infrastructure de configuration WCF. Cela permet d'utiliser les informations d'identification de client personnalisées dans les éléments de comportement de point de terminaison client, tel qu'indiqué dans la procédure suivante.
Pour inscrire et utiliser un gestionnaire de configuration d'informations d'identification de client personnalisées dans la configuration de l'application
Ajoutez un élément
<extensions>
et un élément<behaviorExtensions>
au fichier de configuration.Ajoutez un élément
<add>
à un élément<behaviorExtensions>
, puis affectez à l'attributname
à une valeur appropriée.Affectez le nom de type complet à l'attribut
type
. Incluez également le nom d'assembly ainsi que les autres attributs d'assembly.<system.serviceModel> <extensions> <behaviorExtensions> <add name="myClientCredentials" type="Microsoft.ServiceModel.Samples.MyClientCredentialsConfigHandler, CustomCredentials, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" /> </behaviorExtensions> </extensions> </system.serviceModel>
Après avoir inscrit votre gestionnaire de configuration, l'élément d'informations d'identification personnalisées peut être utilisé à l'intérieur du même fichier de configuration au lieu de l'élément
<clientCredentials>
fourni par le système. Vous pouvez utiliser à la fois les propriétés fournies par le système et les nouvelles propriétés ajoutées à votre implémentation de gestionnaire de configuration. L'exemple suivant définit la valeur d'une propriété personnalisée à l'aide de l'attributcreditCardNumber
.<behaviors> <endpointBehaviors> <behavior name="myClientCredentialsBehavior"> <myClientCredentials creditCardNumber="123-123-123"/> </behavior> </endpointBehaviors> </behaviors>
Pour implémenter des informations d'identification de service personnalisées
Définissez une nouvelle classe dérivée de ServiceCredentials.
facultatif. Ajoutez de nouvelles propriétés pour fournir des API aux nouvelles valeurs d'informations d'identification ajoutées. Si vous n'ajoutez pas de nouvelle valeur d'informations d'identification, ignorez cette étape. L'exemple suivant ajoute une propriété
AdditionalCertificate
.Remplacez la méthode CreateSecurityTokenManager . Cette méthode est automatiquement appelée par l'infrastructure WCF lors de l'utilisation des informations d'identification de client personnalisées. La méthode est chargée de créer et de retourner une instance d'une implémentation de la classe SecurityTokenManager (décrite dans la procédure suivante).
facultatif. Remplacez la méthode CloneCore . Cela est uniquement requis lors de l'ajout de nouvelles propriétés ou de nouveaux champs internes à l'implémentation d'informations d'identification de client personnalisées.
public class MyServiceCredentials : ServiceCredentials { X509Certificate2 additionalCertificate; public MyServiceCredentials() { } protected MyServiceCredentials(MyServiceCredentials other) : base(other) { this.additionalCertificate = other.additionalCertificate; } public X509Certificate2 AdditionalCertificate { get { return this.additionalCertificate; } set { if (value == null) { throw new ArgumentNullException("value"); } this.additionalCertificate = value; } } public override SecurityTokenManager CreateSecurityTokenManager() { return base.CreateSecurityTokenManager(); } protected override ServiceCredentials CloneCore() { return new MyServiceCredentials(this); } }
Public Class MyServiceCredentials Inherits ServiceCredentials Private additionalCertificateValue As X509Certificate2 Public Sub New() End Sub Protected Sub New(ByVal other As MyServiceCredentials) MyBase.New(other) Me.additionalCertificate = other.additionalCertificate End Sub Public Property AdditionalCertificate() As X509Certificate2 Get Return Me.additionalCertificateValue End Get Set If value Is Nothing Then Throw New ArgumentNullException("value") End If Me.additionalCertificateValue = value End Set End Property Public Overrides Function CreateSecurityTokenManager() As SecurityTokenManager Return MyBase.CreateSecurityTokenManager() End Function Protected Overrides Function CloneCore() As ServiceCredentials Return New MyServiceCredentials(Me) End Function End Class
Pour implémenter un gestionnaire de jetons de sécurité de service personnalisé
Définissez une nouvelle classe dérivée de la classe ServiceCredentialsSecurityTokenManager.
facultatif. Substituez la méthode CreateSecurityTokenProvider si une implémentation SecurityTokenProvider personnalisée doit être créée. Pour plus d’informations sur les fournisseurs de jetons de sécurité personnalisés, consultez Procédure : créer un fournisseur de jetons de sécurité personnalisé.
facultatif. Substituez la méthode CreateSecurityTokenAuthenticator si une implémentation SecurityTokenAuthenticator personnalisée doit être créée. Pour plus d’informations sur les authentificateurs de jeton de sécurité personnalisés, consultez la rubrique Procédure : créer un authentificateur de jeton de sécurité personnalisé.
facultatif. Substituez la méthode CreateSecurityTokenSerializer(SecurityTokenVersion) si une implémentation SecurityTokenSerializer personnalisée doit être créée. Pour plus d'informations sur les jetons de sécurité personnalisés et les sérialiseurs de jeton de sécurité personnalisés, consultez Procédure : créer un jeton personnalisé.
internal class MyServiceCredentialsSecurityTokenManager : ServiceCredentialsSecurityTokenManager { MyServiceCredentials credentials; public MyServiceCredentialsSecurityTokenManager(MyServiceCredentials credentials) : base(credentials) { this.credentials = credentials; } public override SecurityTokenProvider CreateSecurityTokenProvider(SecurityTokenRequirement tokenRequirement) { // Return your implementation of SecurityTokenProvider, if required. // This implementation delegates to the base class. return base.CreateSecurityTokenProvider(tokenRequirement); } public override SecurityTokenAuthenticator CreateSecurityTokenAuthenticator(SecurityTokenRequirement tokenRequirement, out SecurityTokenResolver outOfBandTokenResolver) { // Return your implementation of SecurityTokenProvider, if required. // This implementation delegates to the base class. return base.CreateSecurityTokenAuthenticator(tokenRequirement, out outOfBandTokenResolver); } public override SecurityTokenSerializer CreateSecurityTokenSerializer(SecurityTokenVersion version) { // Return your implementation of SecurityTokenProvider, if required. // This implementation delegates to the base class. return base.CreateSecurityTokenSerializer(version); } }
Friend Class MyServiceCredentialsSecurityTokenManager Inherits ServiceCredentialsSecurityTokenManager Private credentials As MyServiceCredentials Public Sub New(ByVal credentials As MyServiceCredentials) MyBase.New(credentials) Me.credentials = credentials End Sub Public Overrides Function CreateSecurityTokenProvider(ByVal tokenRequirement As SecurityTokenRequirement) _ As SecurityTokenProvider ' Return your implementation of SecurityTokenProvider, if required. ' This implementation delegates to the base class. Return MyBase.CreateSecurityTokenProvider(tokenRequirement) End Function Public Overrides Function CreateSecurityTokenAuthenticator( _ ByVal tokenRequirement As SecurityTokenRequirement, _ ByRef outOfBandTokenResolver As SecurityTokenResolver) _ As SecurityTokenAuthenticator ' Return your implementation of SecurityTokenProvider, if required. ' This implementation delegates to the base class. Return MyBase.CreateSecurityTokenAuthenticator(tokenRequirement, outOfBandTokenResolver) End Function Public Overrides Function CreateSecurityTokenSerializer(ByVal version As SecurityTokenVersion) _ As SecurityTokenSerializer ' Return your implementation of SecurityTokenProvider, if required. ' This implementation delegates to the base class. Return MyBase.CreateSecurityTokenSerializer(version) End Function End Class
Pour utiliser des informations d'identification de service personnalisées à partir du code de l'application
Créez une instance de ServiceHost.
Supprimez le comportement d'informations d'identification de service fourni par le système de la collection Behaviors.
Créez une instance de la classe d’informations d’identification de service personnalisées et ajoutez-la à la collection Behaviors.
// Create a service host with a service type. ServiceHost serviceHost = new ServiceHost(typeof(Service)); // Remove the default ServiceCredentials behavior. serviceHost.Description.Behaviors.Remove<ServiceCredentials>(); // Add a custom service credentials instance to the collection. serviceHost.Description.Behaviors.Add(new MyServiceCredentials());
' Create a service host with a service type. Dim serviceHost As New ServiceHost(GetType(Service)) ' Remove the default ServiceCredentials behavior. serviceHost.Description.Behaviors.Remove(Of ServiceCredentials)() ' Add a custom service credentials instance to the collection. serviceHost.Description.Behaviors.Add(New MyServiceCredentials())
Ajoutez la prise en charge de la configuration à l’aide des étapes décrites précédemment dans les procédures « To create a configuration handler for custom client credentials
» et « To register and use a custom client credentials configuration handler in the application configuration
». La seule différence consiste à utiliser la classe ServiceCredentialsElement au lieu de la classe ClientCredentialsElement comme classe de base pour le gestionnaire de configuration. L'élément d'informations d'identification de service personnalisées peut ensuite être utilisé partout où l'élément <serviceCredentials>
fourni par le système est utilisé.
Voir aussi
- ClientCredentials
- ServiceCredentials
- SecurityCredentialsManager
- SecurityTokenManager
- ClientCredentialsElement
- ServiceCredentialsElement
- Procédure : créer un fournisseur de jetons de sécurité personnalisé
- Procédure : créer un authentificateur de jetons de sécurité personnalisé
- Procédure : créer un jeton personnalisé