Panduan: Membuat Mandat Klien dan Layanan Kustom
Topik ini menunjukkan cara menerapkan mandat klien dan layanan kustom dan cara menggunakan mandat kustom dari kode aplikasi.
Kelas Ekstensibilitas Mandat
Kelas ClientCredentials dan ServiceCredentials adalah titik masuk utama ke ekstensibilitas keamanan Windows Communication Foundation (WCF). Kelas mandat ini menyediakan API yang memungkinkan kode aplikasi mengatur informasi mandat dan untuk mengonversi jenis mandat menjadi token keamanan. (Token keamanan adalah formulir yang digunakan untuk mengirimkan informasi mandat di dalam pesan SOAP.) Tanggung jawab kelas mandat ini dapat dibagi menjadi dua area:
Berikan API bagi aplikasi untuk mengatur informasi mandat.
Lakukan sebagai pabrik untuk implementasi SecurityTokenManager.
Implementasi default yang disediakan dalam WCF mendukung jenis mandat yang disediakan sistem dan membuat manajer token keamanan yang mampu menangani jenis mandat tersebut.
Alasan untuk Menyesuaikan
Ada beberapa alasan untuk menyesuaikan kelas mandat klien atau layanan. Yang terpenting adalah persyaratan untuk mengubah perilaku keamanan WCF default sehubungan dengan penanganan jenis mandat yang disediakan sistem, terutama karena alasan berikut:
Perubahan yang tidak dimungkinkan menggunakan titik ekstensibilitas lainnya.
Menambahkan jenis mandat baru.
Menambahkan jenis token keamanan kustom baru.
Topik ini menjelaskan cara menerapkan mandat klien dan layanan kustom dan cara menggunakan mandat kustom dari kode aplikasi.
Pertama dalam Seri
Membuat kelas mandat kustom hanyalah langkah pertama, karena alasan untuk menyesuaikan mndat adalah untuk mengubah perilaku WCF mengenai penyediaan mandat, serialisasi token keamanan, atau autentikasi. Topik lain di bagian ini menjelaskan cara membuat serializer dan pengautentikasi kustom. Dalam hal ini, membuat kelas mandat kustom adalah topik pertama dalam seri ini. Tindakan berikutnya (membuat serializer dan pengautentikasi kustom) hanya dapat dilakukan setelah membuat mandat kustom. Topik tambahan yang dibangun berdasarkan topik ini meliputi:
Prosedur
Untuk menerapkan mandat klien kustom
Tentukan kelas baru turunan dari kelas ClientCredentials.
Opsional. Tambahkan metode atau properti baru untuk jenis mandat baru. Jika Anda tidak menambahkan jenis mandat baru, lewati langkah ini. Contoh berikut menambahkan properti
CreditCardNumber
.Ambil alih metode CreateSecurityTokenManager. Metode ini secara otomatis dipanggil oleh infrastruktur keamanan WCF saat mandat klien kustom digunakan. Metode ini bertanggung jawab untuk membuat dan mengembalikan instans implementasi kelas SecurityTokenManager.
Penting
Penting untuk dicatat bahwa metode CreateSecurityTokenManager ini ditimpa untuk membuat manajer token keamanan kustom. Manajer token keamanan, yang berasal dari ClientCredentialsSecurityTokenManager, harus mengembalikan penyedia token keamanan kustom, yang berasal dari SecurityTokenProvider, untuk membuat token keamanan yang sebenarnya. Jika Anda tidak mengikuti pola ini untuk membuat token keamanan, aplikasi Anda mungkin berfungsi dengan salah saat objek ChannelFactory di-cache (yang merupakan perilaku default untuk proksi klien WCF), berpotensi mengakibatkan peningkatan serangan hak istimewa. Objek mandat kustom di-cache sebagai bagian dari ChannelFactory. Namun, SecurityTokenManager kustom dibuat pada setiap pemanggilan, yang mengurangi ancaman keamanan selama logika pembuatan token ditempatkan di SecurityTokenManager.
Ambil alih metode 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
Untuk menerapkan manajer token keamanan klien kustom
Tentukan kelas baru turunan dari ClientCredentialsSecurityTokenManager.
Opsional. Ambil alih metode CreateSecurityTokenProvider(SecurityTokenRequirement) jika implementasi SecurityTokenProvider kustom harus dibuat. Untuk informasi selengkapnya tentang penyedia token keamanan kustom, lihat Cara: Membuat Penyedia Token Keamanan Kustom.
Opsional. Ambil alih metode CreateSecurityTokenAuthenticator(SecurityTokenRequirement, SecurityTokenResolver) jika implementasi SecurityTokenAuthenticator kustom harus dibuat. Untuk informasi selengkapnya tentang pengautentikasi token keamanan khusus, lihat Cara: Membuat Pengautentikasi Token Keamanan Khusus.
Opsional. Ambil alih metode CreateSecurityTokenSerializer jika SecurityTokenSerializer kustom harus dibuat. Untuk informasi selengkapnya tentang token keamanan dan serializer token keamanan kustom, lihat Cara: Membuat Penyedia Token Kustom.
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
Untuk menggunakan mandat klien kustom dari kode aplikasi
Buat instans klien yang dihasilkan yang mewakili antarmuka layanan, atau buat instans ChannelFactory yang menunjuk ke layanan yang ingin Anda komunikasikan.
Hapus perilaku mandat klien yang disediakan sistem dari koleksi Behaviors, yang dapat diakses melalui properti Endpoint.
Buat instans baru kelas mandat klien kustom dan tambahkan ke koleksi Behaviors, yang dapat diakses melalui properti 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())
Prosedur sebelumnya menunjukkan cara menggunakan mandat klien dari kode aplikasi. Mandat WCF juga dapat dikonfigurasi menggunakan file konfigurasi aplikasi. Menggunakan konfigurasi aplikasi sering lebih disukai daripada pengodean permanen karena memungkinkan modifikasi parameter aplikasi tanpa harus memodifikasi sumber, kompilasi ulang, dan penyebaran ulang.
Prosedur berikutnya menjelaskan cara memberikan dukungan untuk konfigurasi mandat kustom.
Membuat handler konfigurasi untuk mandat klien kustom
Tentukan kelas baru turunan dari ClientCredentialsElement.
Opsional. Tambahkan properti untuk semua parameter konfigurasi tambahan yang ingin Anda ekspos melalui konfigurasi aplikasi. Contoh di bawah ini menambahkan satu properti bernama
CreditCardNumber
.Ambil alih properti BehaviorType untuk mengembalikan jenis kelas mandat klien kustom yang dibuat dengan elemen konfigurasi.
Ambil alih metode CreateBehavior. Metode ini bertanggung jawab untuk membuat dan mengembalikan instans kelas mandat kustom berdasarkan pengaturan yang dimuat dari file konfigurasi. Panggil metode ApplyConfiguration(ClientCredentials) dasar dari metode ini untuk mengambil pengaturan mandat yang disediakan sistem yang dimuat ke dalam instans mandat klien kustom Anda.
Opsional. Jika Anda menambahkan properti tambahan di langkah 2, Anda perlu mengambil alih properti Properties untuk mendaftarkan pengaturan konfigurasi tambahan Anda agar kerangka kerja konfigurasi mengenalinya. Gabungkan properti Anda dengan properti kelas dasar untuk memungkinkan pengaturan yang disediakan sistem dikonfigurasi melalui elemen konfigurasi mandat klien kustom ini.
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
Setelah Anda memiliki kelas handler konfigurasi, ini dapat diintegrasikan ke dalam kerangka kerja konfigurasi WCF. Ini memungkinkan mandat klien kustom digunakan dalam elemen perilaku titik akhir klien, seperti yang ditunjukkan pada prosedur berikutnya.
Untuk mendaftar dan menggunakan handler konfigurasi mandat klien kustom dalam konfigurasi aplikasi
Tambahkan elemen
<extensions>
dan elemen<behaviorExtensions>
ke file konfigurasi.Tambahkan elemen
<add>
ke elemen<behaviorExtensions>
dan atur atributname
ke nilai yang sesuai.Atur atribut
type
ke nama jenis yang sepenuhnya memenuhi syarat. Sertakan juga nama rakitan dan atribut rakitan lainnya.<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>
Setelah mendaftarkan handler konfigurasi Anda, elemen mandat kustom dapat digunakan di dalam file konfigurasi yang sama alih-alih elemen
<clientCredentials>
yang disediakan sistem. Anda dapat menggunakan properti yang disediakan sistem dan properti baru apa pun yang telah Anda tambahkan ke implementasi handler konfigurasi. Contoh berikut menetapkan nilai properti kustom menggunakan atributcreditCardNumber
.<behaviors> <endpointBehaviors> <behavior name="myClientCredentialsBehavior"> <myClientCredentials creditCardNumber="123-123-123"/> </behavior> </endpointBehaviors> </behaviors>
Untuk menerapkan mandat layanan kustom
Tentukan kelas baru turunan dari ServiceCredentials.
Opsional. Tambahkan properti baru untuk menyediakan API untuk nilai mandat baru yang sedang ditambahkan. Jika Anda tidak menambahkan nilai mandat baru, lewati langkah ini. Contoh berikut menambahkan properti
AdditionalCertificate
.Ambil alih metode CreateSecurityTokenManager. Metode ini secara otomatis dipanggil oleh infrastruktur WCF saat mandat klien kustom digunakan. Metode ini bertanggung jawab untuk membuat dan mengembalikan instans implementasi kelas SecurityTokenManager (dijelaskan dalam prosedur berikutnya).
Opsional. Ambil alih metode CloneCore. Ini diperlukan hanya jika menambahkan properti baru atau bidang internal ke implementasi mandat klien kustom.
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
Untuk menerapkan manajer token keamanan layanan kustom
Tentukan kelas baru turunan dari kelas ServiceCredentialsSecurityTokenManager.
Opsional. Ambil alih metode CreateSecurityTokenProvider jika implementasi SecurityTokenProvider kustom harus dibuat. Untuk informasi selengkapnya tentang penyedia token keamanan kustom, lihat Cara: Membuat Penyedia Token Keamanan Kustom.
Opsional. Ambil alih metode CreateSecurityTokenAuthenticator jika implementasi SecurityTokenAuthenticator kustom harus dibuat. Untuk informasi selengkapnya tentang pengautentikasi token keamanan khusus, lihat topik Cara: Membuat Pengautentikasi Token Keamanan Khusus.
Opsional. Ambil alih metode CreateSecurityTokenSerializer(SecurityTokenVersion) jika SecurityTokenSerializer kustom harus dibuat. Untuk informasi selengkapnya tentang token keamanan dan serializer token keamanan kustom, lihat Cara: Membuat Penyedia Token Kustom.
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
Untuk menggunakan mandat layanan kustom dari kode aplikasi
Buat instans ServiceHost.
Hapus perilaku mandat layanan yang disediakan sistem dari koleksi Behaviors.
Buat instans baru kelas mandat layanan kustom dan tambahkan ke koleksi 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())
Tambahkan dukungan untuk konfigurasi menggunakan langkah-langkah yang dijelaskan sebelumnya dalam prosedur "To create a configuration handler for custom client credentials
" dan "To register and use a custom client credentials configuration handler in the application configuration
." Satu-satunya perbedaan adalah menggunakan kelas ServiceCredentialsElement alih-alih kelas ClientCredentialsElement sebagai kelas dasar untuk handler konfigurasi. Elemen mandat layanan kustom kemudian dapat digunakan di mana pun elemen <serviceCredentials>
yang disediakan sistem digunakan.