天天看點

WCF的使用者名+密碼認證方式

概述

今天在做Master Data Service(後面簡稱MDS)項目時需要通過WCF來使用MDS的API,進而對MDS的資料進行操作。在這個過程中,遇到了一個棘手的問題,就是在用戶端調用Web Service時的身份認證問題,于是乎對WCF的認證方式做了一個簡單的了解。在這裡還要感謝蔡總陪我加班一起解決問題,在蔡總的大力支援下問題得以解決。我們解決問題的方式采用了用戶端使用者名+密碼的方式來進行身份認證,這隻是諸多WCF認證方式當中的一種。

使用者名+密碼認證的三種模式

基于使用者名/密碼的使用者憑證通過類型UserNamePasswordClientCredential表示。而在ClientCredentials中,隻讀屬性UserName表示這樣一個使用者憑證。可以按照Windows憑證的方式為ChannelFactory<TChannel>或者ClientBase<TChannel>基于使用者名/密碼憑證。

使用者名/密碼憑證在用戶端的設定很容易,但是我們關心的是服務端采用怎樣的機制來驗證這個憑證。WCF提供了如下三種方式來驗證憑證中使用者名是否和密碼相符:

Windows:将使用者名和密碼映射為Windows帳号和密碼,采用Windows認證;

MembershipProvider:利用配置的MembershipProvider驗證使用者名和密碼;

自定義:通過繼承抽象類UsernamePasswordValidator,自定義使用者名/密碼驗證器進行驗證。

WCF通過枚舉UserNamePasswordValidationMode定了上述三種使用者名/密碼認證模式。該枚舉定義如下,其中Windows是預設選項。

上述三種認證模式的設定最終通過之前提到過的ServiceCredentials這一服務行為進行設定的。從下面的定義我們可以看出,ServiceCredentials定義了隻讀屬性UserNameAuthentication用于基于使用者名/密碼認證的相關設定。屬性的類型為UserNamePasswordServiceCredential,定義其中的UserNamePasswordValidationMode屬性表示采用的認證模式。如果選擇了需要通過屬性MembershipProvider設定采用的MembershipProvider。如果選擇了Custom,則需要通過CustomUserNamePasswordValidator屬性指定你自定義的UserNamePasswordValidator對象。

通過MembershipProvider進行使用者名+密碼的認證

Membership是ASP.NET中一個重要的子產品,旨在進行基于使用者名/密碼的認證和對應的帳号管理。Membership采用政策設計模式,所有的API通過幾個靜态Membership類暴露出來,而相應的功能實作在具體的Membership提供者中。所有的提供者繼承自同一個抽象類MembershipProvider。ASP.NET提供了兩種類型的提供者:SqlMembershipProvider和ActiveDirectoryMembershipProvider。前者将使用者存儲于SQL Server資料庫中,而後者則直接建立在AD之上,本執行個體采用SqlMembershipProvider,在前面一個執行個體示範中,我們建立了以計算服務為場景的解決方案,現在我們直接沿用它。

首要的任務是在用于存儲帳戶資訊的SQL Server資料庫,為此可以先在本地SQL Server建立一個空的資料庫(假設起名為AspNetDb)。接着需要在該資料庫中建立SqlMembershipProvider所需的資料表和相應的存儲過程。這些資料庫對象的建立,需要借助aspnet_regsql.exe這個工具。你隻需要以指令行的方式執行如下aspnet_regsql.exe(無需任何參數),相應的向導就會出現。

在向飛彈出的前兩個窗體中保持預設設定,直接點選“下一步”後,會出現一個資料庫選擇窗體。此時你需要選擇我們剛剛建立的資料庫,點選“确認”後,相關的資料庫對象會為你建立出來。

這些建立出來的資料表可以同時服務于多個應用,所有每一個表中都具有一個名稱為ApplicationId的字段來明确該條記錄對應的應用。而所有應用記錄維護在aspnet_Applications這麼一個表中。現在需要通過執行下面一段SQL腳本在該表中添加一條表示應用的記錄。将其命名為MembershipAuthenticationDemo。

現在資料庫方面已經準備就緒,接着來完成程式設計和配置方面的工作。不打算從新建立一個解決方案,而是直接對之前示範的執行個體進行改造。我們采用自我寄宿的方式,由于Membership隸屬于ASP.NET,是以需要添加System.Web.dll的引用,如果采用的是.NET Frameowrk 4.0(本例所示的配置也是基于該版本),則還需額外添加對System.Web.ApplicationServices.dll的引用。接下來,需要在服務寄宿方面所做的工作就是将下面一段配置整個拷貝到app.config中。

至此,在我們建立的資料庫中并沒有使用者帳戶記錄。為了示範認證效果,我們需要建立相關使用者帳戶記錄。為了友善,我直接将相關的代碼寫在了服務寄宿的代碼中。如下面的代碼片斷所示,在對服務進行寄宿之前,我通過調用Membership的靜态方法CreateUser建立了一個使用者名、密碼和Email分别為xuyue、password01和​​xuyue1000@hotmail​​的帳号。

接下來我們需要對用戶端的配置進行相應的調整,整個配置内容如下面的XML片斷所示。對于這段配置有一點需要注意的是:終結點應用了一個名稱為peerTrustSvcCertValidation的行為,該行為中将服務證書認證模式設定成PeerTrust,是以你需要通過MMC證書管理單元的導出/導入功能将YueXu-PC證書導入到“受信任人(Trusted People)”存儲區。

最後,我們來編寫如下一段用戶端進行服務調用的程式。在下面的代碼中,我進行了兩次服務調用。但是建立服務代理對象的ChannelFactory<ICalculator>被設定了不同的使用者名憑證。其中第一個是正确的使用者名和密碼,後一個卻指定了一個根本不存在的使用者名。

輸出結果:

1: 服務調用成功...

2: 服務調用失敗...