Procedura: creare credenziali client e del servizio personalizzate
In questo argomento viene illustrato come implementare credenziali client e del servizio personalizzate e come utilizzare credenziali personalizzate dal codice dell'applicazione.
Classi di estensibilità delle credenziali
Le classi ClientCredentials e ServiceCredentials sono i punti di ingresso principali per l'estendibilità della sicurezza di Windows Communication Foundation (WCF). Queste classi delle credenziali forniscono le API che consentono al codice dell'applicazione di impostare le informazioni sulle credenziali e convertire i tipi di credenziali in token di sicurezza. (I token di sicurezza sono la forma utilizzata per trasmettere le informazioni sulle credenziali all'interno di messaggi SOAP). Le responsabilità di queste classi di credenziali possono essere divise in due aree:
Fornire le API affinché le applicazioni impostino le informazioni sulle credenziali.
Fungere da factory per le implementazioni SecurityTokenManager.
Le implementazioni predefinite fornite in WCF supportano i tipi di credenziali forniti dal sistema e creano un gestore del token di sicurezza in grado di gestire quei tipi di credenziali.
Motivi di personalizzazione
Esistono più motivi per personalizzare classi di credenziali client o del servizio. È necessario innanzitutto modificare il comportamento della sicurezza predefinito di WCF in merito alla gestione dei tipi di credenziali forniti dal sistema, in particolare per le ragioni seguenti:
Necessità di modifiche che non sono possibili utilizzando altri punti di estensibilità.
Aggiunta di nuovi tipi di credenziali.
Aggiunta di nuovi tipi di token di sicurezza personalizzati.
In questo argomento viene illustrato come implementare credenziali client e del servizio personalizzate e come utilizzarle dal codice dell'applicazione.
Primo passaggio
La creazione di una classe di credenziali personalizzata è solo il primo passaggio, perché il motivo per la personalizzazione delle credenziali è modificare il comportamento di WCF relativo al provisioning delle credenziali, alla serializzazione dei token di sicurezza o all'autenticazione. Negli altri argomenti di questa sezione viene descritto come creare serializzatori e autenticatori personalizzati. In questo caso, la creazione di una classe di credenziali personalizzate è il primo tema dei passaggi. Le azioni successive (creazione di serializzatori e autenticatori personalizzati) possono essere eseguite solo dopo avere creato credenziali personalizzate. Gli argomenti aggiuntivi basati su questo argomento includono:
Procedura: Creare un provider di token di sicurezza personalizzati
Procedura: Creare un autenticatore del token di sicurezza personalizzato
Procedure
Per implementare le credenziali client personalizzate
Definire una nuova classe derivata dalla classe ClientCredentials.
Facoltativo. Aggiungere nuovi metodi o proprietà per nuovi tipi di credenziali. Se non vengono aggiunti nuovi tipi di credenziali, ignorare questo passaggio. Nell'esempio seguente viene aggiunta una proprietà
CreditCardNumber
.Eseguire l'override del metodo CreateSecurityTokenManager. Questo metodo viene chiamato automaticamente dall'infrastruttura di sicurezza WCF quando viene utilizzata la credenziale client personalizzata. Questo metodo è responsabile della creazione e della restituzione di un'istanza di un'implementazione della classe SecurityTokenManager.
Importante
È importante da notare che l'override del metodo CreateSecurityTokenManager viene eseguito per creare un gestore del token di sicurezza personalizzato. Il gestore del token di sicurezza, derivato da ClientCredentialsSecurityTokenManager deve restituire un provider del token di sicurezza personalizzato, derivato da SecurityTokenProvider, per creare il token di sicurezza effettivo. Se non si segue questo modello per creare token di sicurezza, l'applicazione potrebbe funzionare in modo non corretto quando gli oggetti ChannelFactory vengono memorizzati nella cache (comportamento predefinito dei proxy client WCF), provocando un potenziale attacco di tipo elevazione dei privilegi. L'oggetto credenziale personalizzata viene memorizzato nella cache come parte dell'oggetto ChannelFactory. L'oggetto SecurityTokenManager personalizzato viene creato tuttavia a ogni chiamata in modo da limitare la minaccia alla sicurezza se la logica di creazione del token è presente nell'oggetto SecurityTokenManager.
Eseguire l'override del metodo 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
Per implementare un gestore del token di sicurezza client personalizzato
Definire una nuova classe derivata da ClientCredentialsSecurityTokenManager.
Facoltativo. Eseguire l'override del metodo CreateSecurityTokenProvider(SecurityTokenRequirement) se è necessario creare un'implementazione SecurityTokenProvider personalizzata. Per altre informazioni sui provider di token di sicurezza personalizzati, vedere Procedura: Creare un provider di token di sicurezza personalizzati.
Facoltativo. Eseguire l'override del metodo CreateSecurityTokenAuthenticator(SecurityTokenRequirement, SecurityTokenResolver) se è necessario creare un'implementazione SecurityTokenAuthenticator personalizzata. Per altre informazioni sugli autenticatori del token di sicurezza personalizzati, vedere Procedura: Creare un autenticatore del token di sicurezza personalizzato.
Facoltativo. Eseguire l'override del metodo CreateSecurityTokenSerializer se è necessario creare un oggetto SecurityTokenSerializer personalizzato. Per altre informazioni sui token di sicurezza personalizzati e sui serializzatori di token di sicurezza personalizzati, vedere Procedura: Creare un token personalizzato.
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
Per utilizzare credenziali client personalizzate dal codice dell'applicazione
Creare un'istanza del client generato che rappresenta l'interfaccia del servizio oppure creare un'istanza di ChannelFactory che punta a un servizio con il quale si desidera comunicare.
Rimuovere il comportamento delle credenziali client fornite dal sistema dalla raccolta Behaviors, alla quale è possibile accedere tramite la proprietà Endpoint.
Creare una nuova istanza di una classe di credenziali client personalizzate e aggiungerla alla raccolta Behaviors, alla quale è possibile accedere tramite la proprietà 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())
Nella procedura precedente viene illustrato come utilizzare credenziali client dal codice dell'applicazione. Le credenziali WCF possono essere configurate anche utilizzando il file di configurazione dell'applicazione. Spesso è preferibile utilizzare la configurazione dell'applicazione anziché la specifica a livello di codice, perché consente di modificare i parametri dell'applicazione senza dovere modificare l'origine, ricompilare e ridistribuire.
Nella prossima procedura viene illustrato come fornire supporto per la configurazione di credenziali personalizzate.
Creazione di un gestore di configurazione per credenziali client personalizzate
Definire una nuova classe derivata da ClientCredentialsElement.
Facoltativo. Aggiungere proprietà per tutti i parametri di configurazione aggiuntivi che si desidera esporre tramite la configurazione dell'applicazione. Nell'esempio seguente viene aggiunta una proprietà denominata
CreditCardNumber
.Eseguire l'override della proprietà BehaviorType per restituire il tipo di classe di credenziali client personalizzate creata con l'elemento di configurazione.
Eseguire l'override del metodo CreateBehavior. Il metodo è responsabile della creazione e restituzione di un'istanza della classe di credenziali personalizzati basata sulle impostazioni caricate dal file di configurazione. Chiamare il metodo ApplyConfiguration(ClientCredentials) di base da questo metodo per recuperare le impostazioni delle credenziali fornite dal sistema caricate nell'istanza delle credenziali client personalizzate.
Facoltativo. Se nel passaggio 2 sono state aggiunte altre proprietà, è necessario eseguire l'override della proprietà Properties per registrare le impostazioni di configurazione aggiuntive affinché il framework di configurazione le riconosca. Combinare le proprietà con le proprietà della classe di base per consentire la configurazione delle impostazioni fornite dal sistema tramite questo elemento di configurazione delle credenziali client personalizzate.
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
Quando disponibile, la classe del gestore di configurazione può essere integrata nel framework di configurazione di WCF. Ciò consente di utilizzare le credenziali client personalizzate negli elementi di comportamento dell'endpoint client, come illustrato nella procedura seguente.
Per registrare e utilizzare un gestore di configurazione di credenziali client personalizzate nella configurazione dell'applicazione
Aggiungere un elemento
<extensions>
e un elemento<behaviorExtensions>
al file di configurazione.Aggiungere un elemento
<add>
all’elemento<behaviorExtensions>
e impostare l'attributoname
su un valore appropriato.Impostare l'attributo
type
sul nome del tipo completo. Includere inoltre il nome e altri attributi dell'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>
Dopo aver registrato il gestore di configurazione, nello stesso file di configurazione è possibile utilizzare l'elemento delle credenziali personalizzate anziché l'elemento
<clientCredentials>
fornito dal sistema. È possibile utilizzare sia le proprietà fornite dal sistema che qualsiasi nuova proprietà aggiunta all'implementazione del gestore di configurazione. Nell'esempio seguente viene impostato il valore di una proprietà personalizzata utilizzando l'attributocreditCardNumber
.<behaviors> <endpointBehaviors> <behavior name="myClientCredentialsBehavior"> <myClientCredentials creditCardNumber="123-123-123"/> </behavior> </endpointBehaviors> </behaviors>
Per implementare credenziali del servizio personalizzate
Definire una nuova classe derivata da ServiceCredentials.
Facoltativo. Aggiungere nuove proprietà per fornire API per i nuovi valori delle credenziali che vengono aggiunte. Se non vengono aggiunti nuovi valori delle credenziali, ignorare questo passaggio. Nell'esempio seguente viene aggiunta una proprietà
AdditionalCertificate
.Eseguire l'override del metodo CreateSecurityTokenManager. Questo metodo viene chiamato automaticamente dall'infrastruttura WCF quando viene utilizzata la credenziale client personalizzata. Il metodo è responsabile della creazione e della restituzione di un'istanza di un'implementazione della classe SecurityTokenManager, descritta nella procedura seguente.
Facoltativo. Eseguire l'override del metodo CloneCore. È richiesto solo se si aggiungono nuove proprietà o campi interni all'implementazione delle credenziali client personalizzate.
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
Per implementare un gestore del token di sicurezza del servizio personalizzato
Definire una nuova classe derivata dalla classe ServiceCredentialsSecurityTokenManager.
Facoltativo. Eseguire l'override del metodo CreateSecurityTokenProvider se è necessario creare un'implementazione SecurityTokenProvider personalizzata. Per altre informazioni sui provider di token di sicurezza personalizzati, vedere Procedura: Creare un provider di token di sicurezza personalizzati.
Facoltativo. Eseguire l'override del metodo CreateSecurityTokenAuthenticator se è necessario creare un'implementazione SecurityTokenAuthenticator personalizzata. Per altre informazioni sugli autenticatori di token di sicurezza personalizzati, vedere l’argomento Procedura: Creare un autenticatore del token di sicurezza personalizzato.
Facoltativo. Eseguire l'override del metodo CreateSecurityTokenSerializer(SecurityTokenVersion) se è necessario creare un oggetto SecurityTokenSerializer personalizzato. Per altre informazioni sui token di sicurezza personalizzati e sui serializzatori di token di sicurezza personalizzati, vedere Procedura: Creare un token personalizzato.
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
Per utilizzare credenziali del servizio personalizzate dal codice dell'applicazione
Creare un'istanza di ServiceHost.
Rimuovere il comportamento delle credenziali del servizio fornite dal sistema dalla raccolta Behaviors.
Creare una nuova istanza della classe di credenziali del servizio personalizzate e aggiungerla alla raccolta 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())
Aggiungere il supporto per la configurazione utilizzando i passaggi descritti in precedenza nelle procedure "To create a configuration handler for custom client credentials
" e "To register and use a custom client credentials configuration handler in the application configuration
." L'unica differenza è nell'utilizzo della classe ServiceCredentialsElement invece che della classe ClientCredentialsElement come classe di base per il gestore della configurazione. L'elemento credenziale personalizzata del servizio può quindi essere utilizzato ovunque sia utilizzato l'elemento <serviceCredentials>
fornito dal sistema.
Vedi anche
- ClientCredentials
- ServiceCredentials
- SecurityCredentialsManager
- SecurityTokenManager
- ClientCredentialsElement
- ServiceCredentialsElement
- Procedura: Creare un provider di token di sicurezza personalizzati
- Procedura: Creare un autenticatore del token di sicurezza personalizzato
- Procedura: Creare un token personalizzato