此範例示範如何實作自定義令牌提供者。 Windows Communication Foundation (WCF) 中的令牌提供者可用來提供安全性基礎結構的認證。 令牌提供者一般會檢查目標併發出適當的認證,讓安全性基礎結構可以保護訊息。 WCF 隨附預設認證管理員令牌提供者。 WCF 也會隨附 CardSpace 令牌提供者。 自訂代幣提供者在下列情況下很有用:
如果您擁有一個這些令牌提供者無法操作的認證存放區。
如果您想要提供自己的自定義機制,從使用者提供認證資訊到WCF客戶端框架使用認證之間,進行憑證轉換。
如果您要建立自定義令牌。
此範例示範如何建置自定義令牌提供者,以將使用者的輸入轉換成不同的格式。
為了摘要說明,此範例示範下列各項:
用戶端如何使用使用者名稱/密碼組進行驗證。
如何使用自定義令牌提供者來設定用戶端。
伺服器如何通過密碼驗證客戶端憑證,並使用自定義 UserNamePasswordValidator 來驗證使用者名稱和密碼是否相符。
用戶端如何使用伺服器的 X.509 憑證來驗證伺服器。
此範例也會示範在自定義令牌驗證程序之後,呼叫端的身分識別可以被存取。
服務會公開單一端點,以便與服務通訊,並使用組態檔 App.config 定義。 端點是由位址、系結和合約所組成。 系結會設定為標準 wsHttpBinding,預設會使用訊息安全性。 此範例會設定使用用戶端用戶名稱驗證的標準 wsHttpBinding 。 服務也會使用 serviceCredentials 行為來設定服務憑證。 serviceCredentials 行為可讓您設定服務憑證。 用戶端會使用服務憑證來驗證服務並提供訊息保護。 下列組態會參考範例安裝期間所安裝的localhost憑證,如下列安裝指示所述。
<system.serviceModel>
<services>
<service
name="Microsoft.ServiceModel.Samples.CalculatorService"
behaviorConfiguration="CalculatorServiceBehavior">
<host>
<baseAddresses>
<!-- configure base address provided by host -->
<add baseAddress ="http://localhost:8000/servicemodelsamples/service"/>
</baseAddresses>
</host>
<!-- use base address provided by host -->
<endpoint address=""
binding="wsHttpBinding"
bindingConfiguration="Binding1"
contract="Microsoft.ServiceModel.Samples.ICalculator" />
</service>
</services>
<bindings>
<wsHttpBinding>
<binding name="Binding1">
<security mode="Message">
<message clientCredentialType="UserName" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="CalculatorServiceBehavior">
<serviceDebug includeExceptionDetailInFaults="False" />
<!--
The serviceCredentials behavior allows one to define a service certificate.
A service certificate is used by a client to authenticate the service and provide message protection.
This configuration references the "localhost" certificate installed during the setup instructions.
-->
<serviceCredentials>
<serviceCertificate findValue="localhost" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
用戶端端點組態包含組態名稱、服務端點的絕對位址、系結和合約。 用戶端系結是使用適當的 Mode 和訊息 clientCredentialType來設定。
<system.serviceModel>
<client>
<endpoint name=""
address="http://localhost:8000/servicemodelsamples/service"
binding="wsHttpBinding"
bindingConfiguration="Binding1"
contract="Microsoft.ServiceModel.Samples.ICalculator">
</endpoint>
</client>
<bindings>
<wsHttpBinding>
<binding name="Binding1">
<security mode="Message">
<message clientCredentialType="UserName" />
</security>
</binding>
</wsHttpBinding>
</bindings>
</system.serviceModel>
下列步驟示範如何開發自定義令牌提供者,並將其與 WCF 安全性架構整合:
撰寫自定義令牌提供者。
此範例會實作可取得使用者名稱和密碼的自定義令牌提供者。 密碼必須符合此用戶名稱。 此自定義令牌提供者僅供示範之用,不建議用於實際部署。
若要執行這個任務,自訂令牌提供者會衍生 SecurityTokenProvider 類別並覆蓋 GetTokenCore(TimeSpan) 方法。 這個方法會建立並傳回新的
UserNameSecurityToken。protected override SecurityToken GetTokenCore(TimeSpan timeout) { // obtain username and password from the user using console window string username = GetUserName(); string password = GetPassword(); Console.WriteLine("username: {0}", username); // return new UserNameSecurityToken containing information obtained from user return new UserNameSecurityToken(username, password); }撰寫自定義安全性令牌管理員。
SecurityTokenManager 用來在 SecurityTokenProvider 方法中針對特定的 SecurityTokenRequirement 建立
CreateSecurityTokenProvider,並傳遞給它。 安全性令牌管理員也可用來建立令牌驗證器和令牌串行化程式,但此範例並未涵蓋這些驗證器。 在此範例中,客制安全性令牌管理員繼承自 ClientCredentialsSecurityTokenManager 類別,並覆寫CreateSecurityTokenProvider方法,當傳入的令牌需求指明需要用戶名稱提供者時,返回客制用戶名稱令牌提供者。public class MyUserNameSecurityTokenManager : ClientCredentialsSecurityTokenManager { MyUserNameClientCredentials myUserNameClientCredentials; public MyUserNameSecurityTokenManager(MyUserNameClientCredentials myUserNameClientCredentials) : base(myUserNameClientCredentials) { this.myUserNameClientCredentials = myUserNameClientCredentials; } public override SecurityTokenProvider CreateSecurityTokenProvider(SecurityTokenRequirement tokenRequirement) { // if token requirement matches username token return custom username token provider // otherwise use base implementation if (tokenRequirement.TokenType == SecurityTokenTypes.UserName) { return new MyUserNameTokenProvider(); } else { return base.CreateSecurityTokenProvider(tokenRequirement); } } }撰寫自定義客戶端認證。
用戶端認證類別用來代表為用戶端 Proxy 設定的認證,並建立安全性令牌管理員,用來取得令牌驗證器、令牌提供者和令牌串行化程式。
public class MyUserNameClientCredentials : ClientCredentials { public MyUserNameClientCredentials() : base() { } protected override ClientCredentials CloneCore() { return new MyUserNameClientCredentials(); } public override SecurityTokenManager CreateSecurityTokenManager() { // return custom security token manager return new MyUserNameSecurityTokenManager(this); } }將客戶端設定為使用自訂客戶端認證。
為了讓用戶端使用自定義客戶端認證,此範例會刪除預設客戶端認證類別,並提供新的用戶端認證類別。
static void Main() { // ... // Create a client with given client endpoint configuration CalculatorClient client = new CalculatorClient(); // set new credentials client.ChannelFactory.Endpoint.Behaviors.Remove(typeof(ClientCredentials)); client.ChannelFactory.Endpoint.Behaviors.Add(new MyUserNameClientCredentials()); // ... }
在服務上,若要顯示呼叫端的資訊,請使用 PrimaryIdentity ,如下列程式代碼範例所示。 Current包含目前呼叫端的權限資訊。
static void DisplayIdentityInformation()
{
Console.WriteLine("\t\tSecurity context identity : {0}",
ServiceSecurityContext.Current.PrimaryIdentity.Name);
}
當您執行範例時,作業要求和回應會顯示在用戶端控制台視窗中。 在客戶端視窗中按 ENTER 鍵以關閉用戶端。
設定批次處理檔
此範例隨附的 Setup.bat 批處理檔可讓您設定具有相關憑證的伺服器,以執行需要伺服器證書式安全性的自我裝載應用程式。 必須修改此批處理檔,才能跨電腦使用,或在非托管的情況下操作。
下列提供批處理檔不同區段的簡短概觀,以便修改它們以在適當的組態中執行:
建立伺服器證書。
Setup.bat 批處理檔中的下列幾行會建立要使用的伺服器證書。 變數
%SERVER_NAME%會指定伺服器名稱。 變更此變數以指定您自己的伺服器名稱。 此批處理檔中的預設值為localhost。echo ************ echo Server cert setup starting echo %SERVER_NAME% echo ************ echo making server cert echo ************ makecert.exe -sr LocalMachine -ss MY -a sha1 -n CN=%SERVER_NAME% -sky exchange -pe將伺服器憑證安裝到用戶端的受信任憑證儲存中:
Setup.bat 批處理檔中的下列幾行會將伺服器證書複製到用戶端信任的人員存放區。 這是必要步驟,因為客戶端系統不會隱含信任 Makecert.exe 所產生的憑證。 如果您已經有根植於用戶端受信任的根證書的憑證,例如,Microsoft 發行的憑證,則不需要執行使用伺服器證書填入用戶端證書存儲的此步驟。
certmgr.exe -add -r LocalMachine -s My -c -n %SERVER_NAME% -r CurrentUser -s TrustedPeople
備註
Setup.bat 批處理文件的設計目的是要從 Windows SDK 命令提示字元執行。 它要求 MSSDK 環境變數指向安裝 SDK 的目錄。 此環境變數會在 Windows SDK 命令提示字元內自動設定。
若要設定和建置範例
請確定您已針對 Windows Communication Foundation 範例 執行One-Time 安裝程式。
若要建置解決方案,請遵循 建置 Windows Communication Foundation 範例中的指示。
在同一部電腦上執行這個範例
從 Visual Studio 命令提示字元內以系統管理員許可權開啟的範例安裝資料夾執行 Setup.bat。 這會安裝執行範例所需的所有憑證。
備註
Setup.bat 批處理文件的設計目的是要從 Visual Studio 命令提示字元執行。 Visual Studio 命令提示字元內設定的PATH環境變數會指向包含 Setup.bat 腳本所需可執行檔案的目錄。
從 service\bin 啟動 service.exe。
從 \client\bin 啟動 Client.exe。 用戶端活動會顯示在用戶端主控台應用程式上。
在使用者名稱提示字元中,輸入用戶名稱。
在密碼提示中,使用與使用者名稱提示相同的字串。
如果客戶端和服務無法通訊,請參閱 WCF 範例 的疑難解答秘訣。
在多台電腦上執行範例
在服務電腦上為服務的二進位檔案建立目錄。
將服務程式檔案複製到服務電腦上的服務目錄。 同時將 Setup.bat 和 Cleanup.bat 檔案複製到服務計算機。
您必須擁有包含電腦完整域名的主體名稱的伺服器證書。 必須更新 Service.exe.config 檔案,才能反映這個新的憑證名稱。 您可以修改 Setup.bat 批次處理檔來建立伺服器證書。 請注意,setup.bat 檔案必須從以系統管理員許可權開啟的Visual Studio開發人員命令提示字元執行。 您必須將
%SERVER_NAME%變數設定為用來裝載服務之電腦的完整限定主機名稱。將伺服器證書複製到用戶端 CurrentUser-TrustedPeople 存放區。 當用戶端信任的簽發者發出伺服器證書時,您不需要這麼做。
在服務計算機上的 Service.exe.config 檔案中,變更基位址的值,以指定完整計算機名稱,而不是localhost。
在服務計算機上,從命令提示字元執行 service.exe。
將用戶端程式檔案從語言特定資料夾下的 \client\bin\ 資料夾,複製到用戶端電腦。
在用戶端電腦上的 Client.exe.config 檔案中,變更端點的位址值,以符合您服務的新位址。
在用戶端電腦上,從命令提示字元窗口啟動
Client.exe。如果客戶端和服務無法通訊,請參閱 WCF 範例 的疑難解答秘訣。
在範例之後清除
- 在您完成執行範例之後,請在samples資料夾中執行 Cleanup.bat。