Genomgång: Skapa anpassade klient- och tjänstautentiseringsuppgifter
Det här avsnittet visar hur du implementerar anpassade klient- och tjänstautentiseringsuppgifter och hur du använder anpassade autentiseringsuppgifter från programkod.
Utökningsbarhetsklasser för autentiseringsuppgifter
Klasserna ClientCredentials och ServiceCredentials är de viktigaste startpunkterna för utökningsbarheten för Windows Communication Foundation (WCF). Dessa autentiseringsuppgifter ger API:er som gör det möjligt för programkod att ange information om autentiseringsuppgifter och konvertera typer av autentiseringsuppgifter till säkerhetstoken. (Säkerhetstoken är det formulär som används för att överföra information om autentiseringsuppgifter i SOAP-meddelanden.) Ansvarsområdena för dessa autentiseringsuppgifter kan delas in i två områden:
Ange API:er för program för att ange information om autentiseringsuppgifter.
Utför som en fabrik för SecurityTokenManager implementeringar.
Standardimplementeringarna som tillhandahålls i WCF stöder systemspecifika typer av autentiseringsuppgifter och skapar en säkerhetstokenhanterare som kan hantera dessa typer av autentiseringsuppgifter.
Anledningar att anpassa
Det finns flera orsaker till att anpassa antingen klient- eller tjänstautentiseringsklasser. Det främsta är kravet på att ändra standardbeteendet för WCF-säkerhet när det gäller hantering av systemspecifika autentiseringstyper, särskilt av följande skäl:
Ändringar som inte är möjliga med hjälp av andra utökningspunkter.
Lägga till nya typer av autentiseringsuppgifter.
Lägga till nya anpassade typer av säkerhetstoken.
Det här avsnittet beskriver hur du implementerar anpassade klient- och tjänstautentiseringsuppgifter och hur du använder dem från programkod.
Först i en serie
Att skapa en klass för anpassade autentiseringsuppgifter är bara det första steget eftersom anledningen till att anpassa autentiseringsuppgifter är att ändra WCF-beteende när det gäller etablering av autentiseringsuppgifter, serialisering av säkerhetstoken eller autentisering. Andra avsnitt i det här avsnittet beskriver hur du skapar anpassade serialiserare och autentiseringsprogram. I det här avseendet är det första ämnet i serien att skapa en anpassad klass för autentiseringsuppgifter. Efterföljande åtgärder (skapa anpassade serialiserare och autentiserare) kan bara utföras när anpassade autentiseringsuppgifter har skapats. Ytterligare ämnen som bygger på det här avsnittet är:
Förfaranden
Så här implementerar du anpassade klientautentiseringsuppgifter
Definiera en ny klass som härleds ClientCredentials från klassen.
Valfritt. Lägg till nya metoder eller egenskaper för nya typer av autentiseringsuppgifter. Om du inte lägger till nya typer av autentiseringsuppgifter hoppar du över det här steget. I följande exempel läggs en
CreditCardNumber
egenskap till.Åsidosätt CreateSecurityTokenManager metoden. Den här metoden anropas automatiskt av WCF-säkerhetsinfrastrukturen när den anpassade klientautentiseringsuppgiften används. Den här metoden ansvarar för att skapa och returnera en instans av en implementering av SecurityTokenManager klassen.
Viktigt!
Observera att CreateSecurityTokenManager metoden åsidosätts för att skapa en anpassad säkerhetstokenhanterare. Säkerhetstokenhanteraren, härledd från ClientCredentialsSecurityTokenManager, måste returnera en anpassad säkerhetstokenprovider, härledd från SecurityTokenProvider, för att skapa den faktiska säkerhetstoken. Om du inte följer det här mönstret för att skapa säkerhetstoken kan programmet fungera felaktigt när ChannelFactory objekt cachelagras (vilket är standardbeteendet för WCF-klientproxyservrar), vilket kan leda till utökade privilegier. Det anpassade autentiseringsobjektet cachelagras som en del av ChannelFactory. Den anpassade SecurityTokenManager skapas dock för varje anrop, vilket minimerar säkerhetshotet så länge logiken för tokenskapande placeras i SecurityTokenManager.
Åsidosätt CloneCore metoden.
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
Implementera en anpassad klientsäkerhetstokenhanterare
Definiera en ny klass som härletts från ClientCredentialsSecurityTokenManager.
Valfritt. Åsidosätt CreateSecurityTokenProvider(SecurityTokenRequirement) metoden om en anpassad SecurityTokenProvider implementering måste skapas. Mer information om anpassade leverantörer av säkerhetstoken finns i Så här skapar du en anpassad säkerhetstokenprovider.
Valfritt. Åsidosätt CreateSecurityTokenAuthenticator(SecurityTokenRequirement, SecurityTokenResolver) metoden om en anpassad SecurityTokenAuthenticator implementering måste skapas. Mer information om autentisering av anpassade säkerhetstoken finns i Så här skapar du en anpassad säkerhetstokenautentisering.
Valfritt. Åsidosätt CreateSecurityTokenSerializer metoden om en anpassad SecurityTokenSerializer måste skapas. Mer information om anpassade säkerhetstoken och serialiserare för anpassade säkerhetstoken finns i Så här skapar du en anpassad token.
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
Så här använder du en anpassad klientautentiseringsuppgifter från programkoden
Skapa antingen en instans av den genererade klienten som representerar tjänstgränssnittet eller skapa en instans av den ChannelFactory som pekar på en tjänst som du vill kommunicera med.
Ta bort beteendet för klientautentiseringsuppgifter som tillhandahålls av systemet från Behaviors samlingen, som kan nås via egenskapen Endpoint .
Skapa en ny instans av en klass för anpassade klientautentiseringsuppgifter och lägg till den i Behaviors samlingen, som kan nås via Endpoint egenskapen .
// 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())
Föregående procedur visar hur du använder klientautentiseringsuppgifter från programkod. WCF-autentiseringsuppgifter kan också konfigureras med hjälp av programkonfigurationsfilen. Att använda programkonfiguration är ofta att föredra framför hårdkodning eftersom det möjliggör ändring av programparametrar utan att behöva ändra källan, omkompilera och distribuera om.
I nästa procedur beskrivs hur du ger stöd för konfiguration av anpassade autentiseringsuppgifter.
Skapa en konfigurationshanterare för anpassade klientautentiseringsuppgifter
Definiera en ny klass som härletts från ClientCredentialsElement.
Valfritt. Lägg till egenskaper för alla ytterligare konfigurationsparametrar som du vill exponera via programkonfigurationen. Exemplet nedan lägger till en egenskap med namnet
CreditCardNumber
.Åsidosätt BehaviorType egenskapen för att returnera typen av klassen för anpassade klientautentiseringsuppgifter som skapats med konfigurationselementet.
Åsidosätt CreateBehavior metoden. Metoden ansvarar för att skapa och returnera en instans av den anpassade autentiseringsklassen baserat på de inställningar som läses in från konfigurationsfilen. Anropa basmetoden ApplyConfiguration(ClientCredentials) från den här metoden för att hämta inställningarna för systembaserade autentiseringsuppgifter som lästs in i din instans av anpassade klientautentiseringsuppgifter.
Valfritt. Om du har lagt till ytterligare egenskaper i steg 2 måste du åsidosätta Properties egenskapen för att kunna registrera ytterligare konfigurationsinställningar för konfigurationsramverket för att identifiera dem. Kombinera dina egenskaper med basklassegenskaperna så att de systembaserade inställningarna kan konfigureras via det här konfigurationselementet för anpassade klientautentiseringsuppgifter.
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
När du har konfigurationshanterarklassen kan den integreras i WCF-konfigurationsramverket. Det gör att de anpassade klientautentiseringsuppgifterna kan användas i klientslutpunktsbeteendeelementen, som du ser i nästa procedur.
Registrera och använda en konfigurationshanterare för anpassade klientautentiseringsuppgifter i programkonfigurationen
Lägg till ett
<extensions>
element och ett<behaviorExtensions>
element i konfigurationsfilen.Lägg till ett
<add>
element i elementet<behaviorExtensions>
och angename
attributet till ett lämpligt värde.type
Ange attributet till det fullständigt kvalificerade typnamnet. Inkludera även sammansättningsnamnet och andra sammansättningsattribut.<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>
När du har registrerat konfigurationshanteraren kan elementet för anpassade autentiseringsuppgifter användas i samma konfigurationsfil i stället för det systembaserade
<clientCredentials>
elementet. Du kan använda både de systemspecifika egenskaperna och alla nya egenskaper som du har lagt till i konfigurationshanterarimplementeringen. I följande exempel anges värdet för en anpassad egenskap med hjälp av attributetcreditCardNumber
.<behaviors> <endpointBehaviors> <behavior name="myClientCredentialsBehavior"> <myClientCredentials creditCardNumber="123-123-123"/> </behavior> </endpointBehaviors> </behaviors>
Så här implementerar du autentiseringsuppgifter för anpassade tjänster
Definiera en ny klass som härletts från ServiceCredentials.
Valfritt. Lägg till nya egenskaper för att tillhandahålla API:er för nya autentiseringsvärden som läggs till. Om du inte lägger till nya autentiseringsvärden hoppar du över det här steget. I följande exempel läggs en
AdditionalCertificate
egenskap till.Åsidosätt CreateSecurityTokenManager metoden. Den här metoden anropas automatiskt av WCF-infrastrukturen när den anpassade klientautentiseringsuppgiften används. Metoden ansvarar för att skapa och returnera en instans av en implementering av SecurityTokenManager klassen (beskrivs i nästa procedur).
Valfritt. Åsidosätt CloneCore metoden. Detta krävs endast om du lägger till nya egenskaper eller interna fält i implementeringen av anpassade klientautentiseringsuppgifter.
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
Implementera en anpassad tjänstsäkerhetstokenhanterare
Definiera en ny klass som härleds ServiceCredentialsSecurityTokenManager från klassen.
Valfritt. Åsidosätt CreateSecurityTokenProvider metoden om en anpassad SecurityTokenProvider implementering måste skapas. Mer information om anpassade leverantörer av säkerhetstoken finns i Så här skapar du en anpassad säkerhetstokenprovider.
Valfritt. Åsidosätt CreateSecurityTokenAuthenticator metoden om en anpassad SecurityTokenAuthenticator implementering måste skapas. Mer information om anpassade autentiseringsprogram för säkerhetstoken finns i avsnittet Så här skapar du en anpassad säkerhetstokenautentisering .
Valfritt. Åsidosätt CreateSecurityTokenSerializer(SecurityTokenVersion) metoden om en anpassad SecurityTokenSerializer måste skapas. Mer information om anpassade säkerhetstoken och serialiserare för anpassade säkerhetstoken finns i Så här skapar du en anpassad token.
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
Så här använder du autentiseringsuppgifter för anpassad tjänst från programkod
Skapa en instans av ServiceHost.
Ta bort beteendet för tjänstautentiseringsuppgifter som tillhandahålls av Behaviors systemet från samlingen.
Skapa en ny instans av klassen för anpassade tjänstautentiseringsuppgifter och lägg till den i Behaviors samlingen.
// 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())
Lägg till stöd för konfiguration med hjälp av stegen som beskrevs tidigare i procedurerna "To create a configuration handler for custom client credentials
" och "To register and use a custom client credentials configuration handler in the application configuration
". Den enda skillnaden är att använda ServiceCredentialsElement klassen i stället för ClientCredentialsElement klassen som basklass för konfigurationshanteraren. Autentiseringselementet för anpassade tjänster kan sedan användas varhelst det systembaserade <serviceCredentials>
elementet används.