天天看點

WinForm企業應用架構設計【五】系統登入以及身份驗證+源碼

索引

<a href="http://www.cnblogs.com/liulun/archive/2011/11/29/2268337.html">WinForm企業應用架構設計【一】界限劃分與動态建立WCF服務(no svc!no serviceActivations!)</a>

<a href="http://www.cnblogs.com/liulun/archive/2011/11/30/2269602.html">WinForm企業應用架構設計【二】團隊内部的約定和用戶端按約定識别WCF服務</a>

<a href="http://www.cnblogs.com/liulun/archive/2011/12/04/2275097.html">WinForm企業應用架構設計【三】架構窗體設計;動态建立菜單;</a>

<a href="http://www.cnblogs.com/liulun/archive/2011/12/08/2280110.html">WinForm企業應用架構設計【四】動态建立業務窗體</a>

<a href="http://www.cnblogs.com/liulun/archive/2011/12/16/2290800.html">WinForm企業應用架構設計【五】系統登入以及身份驗證+源碼</a>

閑話休提~

一:登入的畫面與用戶端邏輯

WinForm企業應用架構設計【五】系統登入以及身份驗證+源碼

為了在打開程式的時候先彈出登入窗體

我們修改了主窗體的構造函數

如下:

登入窗體中登入和取消按鈕的事件代碼如下

當點選登入之後,

會把使用者輸入的使用者名和密碼傳迪到服務端,并得到目前使用者實體

CacheStrategy.CurUser = CurUser;

這裡隻是一個靜态屬性,沒有做額外的工作,就不多解釋了,

二:每次與WCF互動都傳遞辨別資訊

登入的過程其實沒有什麼特殊的

特殊的是,登入之後的每次服務端互動,

服務端都要确認目前的用戶端的正确性

為了做到這一點,

我們就要在每次與WCF互動的時候,

把用戶端的身份傳遞給伺服器端,并在服務端緩存起來。

我們修改了之前文章中提到的ClientFactory類

var curId = CacheStrategy.CurUser == null ? Guid.Empty : CacheStrategy.CurUser.Id;

            MessageHeader&lt;Guid&gt; mhg = new MessageHeader&lt;Guid&gt;(Guid.Empty);

            MessageHeader untyped = mhg.GetUntypedHeader("token", "ns");

            OperationContext.Current.OutgoingMessageHeaders.Add(untyped);

這幾句為SOAP消息頭增加了一個值

這個值就是登入成功後的UserId

每次與WCF的互動操作都會傳遞這個值

三.服務端的驗證

為了對用戶端的操作進行身份驗證

我們設計了一個所有服務類的基類

虛方法CheckLogin負責驗證用戶端是否登入成功

[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]

[ServiceBehavior(IncludeExceptionDetailInFaults = true)]

此兩個類屬性放在服務基類裡

服務子類就不用再寫這兩個屬性了

var curId = OperationContext.Current.IncomingMessageHeaders.GetHeader&lt;Guid&gt;("token", "ns");

這一句得到了我們在用戶端傳上來的UserId

在登入邏輯的服務類裡,我們重寫了CheckLogin方法

因為登入的時候就不用再做驗證了,是以我們的重寫方法就沒有任何代碼

CacheStrategy.AddObject(result.Id, result);

就是把目前登入的使用者存入緩存裡

緩存我們用的是HttpRuntime的Cache

因為我們的WCF是基于WEB的

是以很自然的用了這個

代碼如下

四:用戶端對驗證消息的處理

在服務端基類裡我們對驗證不通過的客戶抛出了一個異常

throw new Exception("#請重新登入#");

(Exception這個類型的異常相對于其他類型的異常來說,是最後被處理的)

再來看看我們擷取所有菜單的代碼

當服務端有異常發生時,我們交給了Utils類去處理

如果異常,服務端“特意”傳回的

我們就讓用戶端重新登入

好吧!

就這些東西~

----------------------------------------

遺留問題

我試圖在ClientFactory中擷取服務端回報的錯誤

((IClientChannel)proxy).Faulted += new EventHandler(a_Faulted);

但這個事件是抓不到服務端錯誤消息的内容的

不能優美的解決用戶端對驗證消息的處理邏輯

這個系列到此将告一段落

以後或許我會寫增加更多東西

比如通用的權限、人事管理、定制表單、定制流程等

此為後話

我正在研究一個在silverlight上實作的類似的架構

已略有小成

再寫silverlight的東西

(透露一下,我已經把那個工具做成了,自由度非常高的打包工具,您可以用他來打包dotnet 2\3.5\4,以及其他的在系統資料庫裡留下痕迹的東西)

如各位所願

我公布出代碼和資料庫備份(親,資料庫是SQL2008的)

<a href="http://files.cnblogs.com/liulun/XL.zip">點此下載下傳</a>

親,也希望你們如我所願的幫我點推薦吧-&gt;-&gt;-&gt;-&gt;-&gt;-&gt;-&gt;-&gt;-&gt;-&gt;-&gt;-&gt;-&gt;-&gt;

因為你們的支援才是我的動力

歡迎與我交流!!!

-----------------------------------------