作法:使用自訂使用者名稱與密碼驗證程式
根據預設,使用使用者名稱和密碼進行驗證時,Windows Communication Foundation (WCF) 會使用 Windows 驗證使用者名稱和密碼。 不過,WCF 允許自訂的使用者名稱和密碼驗證結構描述,也稱為驗證程式。 若要納入自訂的使用者名稱和密碼驗證程式,請建立衍生自 UserNamePasswordValidator 的類別,然後予以設定。
如需應用程式範例,請參閱使用者名稱密碼驗證程式。
建立自訂的使用者名稱和密碼驗證程式
建立衍生自 UserNamePasswordValidator 的類別。
public class CustomUserNameValidator : UserNamePasswordValidator {
Public Class CustomUserNameValidator Inherits UserNamePasswordValidator
覆寫 Validate 方法,實作自訂驗證結構描述。
請勿在實際執行環境使用下列範例中會覆寫 Validate 方法的程式碼。 將此程式碼以自訂的使用者名稱和密碼驗證結構描述取代,其中可能包含從資料庫擷取使用者名稱和密碼組。
若要將驗證錯誤傳回至用戶端,請在 FaultException 方法中擲回 Validate。
// This method validates users. It allows in two users, test1 and test2 // with passwords 1tset and 2tset respectively. // This code is for illustration purposes only and // must not be used in a production environment because it is not secure. public override void Validate(string userName, string password) { if (null == userName || null == password) { throw new ArgumentNullException(); } if (!(userName == "test1" && password == "1tset") && !(userName == "test2" && password == "2tset")) { // This throws an informative fault to the client. throw new FaultException("Unknown Username or Incorrect Password"); // When you do not want to throw an informative fault to the client, // throw the following exception. // throw new SecurityTokenException("Unknown Username or Incorrect Password"); } }
' This method validates users. It allows in two users, test1 and test2 ' with passwords 1tset and 2tset respectively. ' This code is for illustration purposes only and ' must not be used in a production environment because it is not secure. Public Overrides Sub Validate(ByVal userName As String, ByVal password As String) If Nothing = userName OrElse Nothing = password Then Throw New ArgumentNullException() End If If Not (userName = "test1" AndAlso password = "[PLACEHOLDER]") AndAlso Not (userName = "test2" AndAlso password = "[PLACEHOLDER]") Then ' This throws an informative fault to the client. Throw New FaultException("Unknown Username or Incorrect Password") ' When you do not want to throw an informative fault to the client, ' throw the following exception: ' Throw New SecurityTokenException("Unknown Username or Incorrect Password") End If End Sub
將服務設定為使用自訂的使用者名稱和密碼驗證程式
設定繫結,此繫結會在 HTTP(S) 上的任何傳輸或傳輸層級安全性使用訊息安全性。
使用訊息安全性時,請新增其中一個系統提供的繫結,例如 <wsHttpBinding>,或是支援訊息安全性和
UserName
認證型別的 <customBinding>。使用透過 HTTP(S) 的傳輸層級安全性時,請新增使用 HTTP(S) 和
Basic
驗證配置的 <wsHttpBinding> 或 <basicHttpBinding>、<netTcpBinding> 或 <customBinding>。注意
使用 .NET Framework 3.5 或更新版本時,您可以將自訂使用者名稱和密碼驗證器搭配訊息安全性和傳輸安全性使用。 透過 WinFX,自訂使用者名稱和密碼驗證器只能與訊息安全性配合使用。
提示
如需在此內容中使用 <netTcpBinding> 的詳細資訊,請參閱<安全性>。
在組態檔的 <system.serviceModel> 元素下,新增 <bindings> 元素。
將 <wsHttpBinding> 或 <basicHttpBinding> 元素新增至 bindings 區段。 如需如何建立 WCF 繫結元素的詳細資訊,請參閱如何:在設定中指定服務繫結。
將 <security> 或 <security> 的
mode
屬性設定為Message
、Transport
或TransportWithMessageCredential
。設定 <message> 或 <transport> 的
clientCredentialType
屬性。使用訊息安全性時,將 <message> 的
clientCredentialType
屬性設定為UserName
。使用透過 HTTP(S) 的傳輸層級安全性時,請將 <transport> 或 <transport> 的
clientCredentialType
屬性設定為Basic
。注意
當 WCF 服務使用傳輸層級安全性裝載在網際網路資訊服務 (IIS) 中,並且 UserNamePasswordValidationMode 屬性設定為 Custom 時,自訂驗證配置會使用 Windows 驗證的子集。 這是因為在這種情況中,IIS 會在 WCF 叫用自訂驗證器之前,先執行 Windows 驗證。
如需如何建立 WCF 繫結元素的詳細資訊,請參閱如何:在設定中指定服務繫結。
下列程式碼範例顯示繫結的組態程式碼:
<system.serviceModel> <bindings> <wsHttpBinding> <binding name="Binding1"> <security mode="Message"> <message clientCredentialType="UserName" /> </security> </binding> </wsHttpBinding> </bindings> </system.serviceModel>
設定行為,指定自訂使用者名稱和密碼驗證程式用來驗證傳入之 UserNameSecurityToken 安全性權杖的使用者名稱和密碼組。
作為 <system.serviceModel> 元素的子系,新增 <behaviors> 元素。
將 <serviceBehaviors> 新增至 <behaviors> 元素。
新增 <behavior> 元素,並將
name
屬性設定為適當值。將 <serviceCredentials> 新增至 <behavior> 元素。
將
userNamePasswordValidationMode
設定為Custom
。重要
如果沒有設定
userNamePasswordValidationMode
值,則 WCF 會使用 Windows 驗證,而不會使用自訂的使用者名稱和密碼驗證程式。將
customUserNamePasswordValidatorType
設為代表自訂使用者名稱和密碼驗證程式的類型。
下列範例顯示目前的
<serviceCredentials>
片段:<serviceCredentials> <userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="Microsoft.ServiceModel.Samples.CalculatorService.CustomUserNameValidator, service" /> </serviceCredentials>
範例
以下程式碼範例將示範如何建立自訂的使用者名稱和密碼驗證程式。 請勿在實際執行環境使用會覆寫 Validate 方法的程式碼。 將此程式碼以自訂的使用者名稱和密碼驗證結構描述取代,其中可能包含從資料庫擷取使用者名稱和密碼組。
using System;
using System.IdentityModel.Selectors;
using System.IdentityModel.Tokens;
using System.Security.Principal;
using System.ServiceModel;
Imports System.IdentityModel.Selectors
Imports System.IdentityModel.Tokens
Imports System.Security.Principal
Imports System.ServiceModel
public class CustomUserNameValidator : UserNamePasswordValidator
{
// This method validates users. It allows in two users, test1 and test2
// with passwords 1tset and 2tset respectively.
// This code is for illustration purposes only and
// must not be used in a production environment because it is not secure.
public override void Validate(string userName, string password)
{
if (null == userName || null == password)
{
throw new ArgumentNullException();
}
if (!(userName == "test1" && password == "1tset") && !(userName == "test2" && password == "2tset"))
{
// This throws an informative fault to the client.
throw new FaultException("Unknown Username or Incorrect Password");
// When you do not want to throw an informative fault to the client,
// throw the following exception.
// throw new SecurityTokenException("Unknown Username or Incorrect Password");
}
}
}
Public Class CustomUserNameValidator
Inherits UserNamePasswordValidator
' This method validates users. It allows in two users, test1 and test2
' with passwords 1tset and 2tset respectively.
' This code is for illustration purposes only and
' must not be used in a production environment because it is not secure.
Public Overrides Sub Validate(ByVal userName As String, ByVal password As String)
If Nothing = userName OrElse Nothing = password Then
Throw New ArgumentNullException()
End If
If Not (userName = "test1" AndAlso password = "[PLACEHOLDER]") AndAlso Not (userName = "test2" AndAlso password = "[PLACEHOLDER]") Then
' This throws an informative fault to the client.
Throw New FaultException("Unknown Username or Incorrect Password")
' When you do not want to throw an informative fault to the client,
' throw the following exception:
' Throw New SecurityTokenException("Unknown Username or Incorrect Password")
End If
End Sub
End Class