上篇文章介紹瞭如何在ASP.NET MVC項目中引入Identity組件來實現用戶註冊、登錄及身份驗證功能,並且也提到了Identity是集成到Owin中的,本章就來介紹一下什麼是Owin以及如何使用Owin來增強Identity的功能。 本章的主要內容有: ● 什麼是Owin ● 關於Katana ...
上篇文章介紹瞭如何在ASP.NET MVC項目中引入Identity組件來實現用戶註冊、登錄及身份驗證功能,並且也提到了Identity是集成到Owin中的,本章就來介紹一下什麼是Owin以及如何使用Owin來增強Identity的功能。
本章的主要內容有:
● 什麼是Owin
● 關於Katana
● Owin與宿主IIS
● Owin與Identity的集成
● Identity在Owin中的特殊用法
什麼是Owin
Owin(Open Web Server Interface)它是一個.NET Web伺服器和Web程式之間的介面標準,其目的是為了應用程式與伺服器解耦。為什麼需要解耦?因為ASP.NET應用(不包含ASP.NET Core和mono)都需要部署在IIS伺服器上,而通過實現Owin的介面,可以將一個控制台程式作為Web應用程式的宿主。
Owin實質上是提供了一個名稱為環境字典的IDictionary<string, object>類型來存儲所有數據,包括請求和響應數據。在這個字典中Owin定義了一系列的核心鍵值對:
另外還有一個重要的核心類型是一個參數為IDictionary<string, object>(即上面分析用於存儲數據的類型)的代理:Func<IDictionary<string, object>, Task>,每一個委托都是用於處理請求的一個獨立單元,將多個獨立單元集合到一起就形成了Owin的處理管道,另外返回值是一個Task,換句話說所有的處理單元或者說中間件都需要設計成非同步的,可以提高系統的吞吐量。
更多信息可參考文檔:http://owin.org/html/owin.html
關於Katana
Owin既然是一個介面標準,那麼就一定有實現,微軟對Owin的實現是一個名為Katana的項目(https://github.com/aspnet/AspNetKatana),該項目中的組件大部分以Microsoft.Owin作為首碼,一下是github上部分組件目錄:
Katana主要有4個部分組成,分別是宿主、伺服器、中間件和應用,如下圖整個結構是分層次的,由下到上:
● Host:也就是宿主,使用Katana可選Owin的宿主有IIS、自定義宿主(如console程式)以及OwinHost.exe。前面兩個比較好理解,對於OwinHost.exe其實是Katana項目的一個用於啟動Owin應用的程式,通過命令行的方式就可以運行指定的Owin應用(註:所有的宿主都可以通過Nuget管理器安裝)。
● Server:伺服器,就是用來接收、響應請求的組件。
○ 在IIS下,通過安裝Microsoft.Owin.Host.SystemWeb,將Owin的HttpModule“動態”註冊到IIS處理管道中接收處理HTTP請求。
○ 在自定義的宿主中,通過安裝Microsoft.Owin.Host.HttpListener,以代碼的形式顯式的根據地址和埠打開一個Soket來監聽請求。OwinHost.exe也是使用該組件來監聽請求。
● Middleware:中間件,實質上就是一個實現了Func<IDictionary<string, object>, Task>的委托,也可以簡單通過繼承OwinMiddleware類型來創建。創建完成後在Owin的Startup類型中通過IAppBuilder類型Use方法將其添加到管道中。
● Application:應用層,Owin以及Katana都沒有考慮一種新的開發應用的方式,換句話說可以沿用之前的mvc、webapi、Signalr或者是靜態頁面等方式來開發應用。
Owin與宿主IIS
Owin在IIS的宿主(Microsoft.Owin.Host.SystemWeb)其實是一個IHttpModule的實現:
而使用HttpModule對IIS的請求處理管理進行拓展的一般方法都是使用配置的方式在Web.config文件中添加。但是引入Owin後其實沒有在配置文件裡面加入任何配置,而是通過以下代碼在程式運行時註冊的:
Owin在使用IIS作為宿主時就是通過HttpModule的形式對原有的ASP.NET HTTP請求通道進行了拓展,請求在ASP.NET的管道處理過程中通過HttpModule拓展的形式將整個請求轉移到Owin管道處理。
Owin與Identity的集成
Identity就是通過Owin中間件的方式集成到處理管道中的,如下圖代碼:
另外在安裝Identity的同時還在Web.config文件中加入了以下配置:
刪除了Form驗證的HttpModule,這裡的原因也是identity的驗證可以代替Form驗證,所以對這個功能進行了刪除。
運行時的HttpModule列表:
Identity在Owin中的特殊用法
(註:以下代碼可以參考ASP.NET MVC預設帶有身份驗證的項目模板,部分代碼有改動DbContext名稱、命名空間以及省略了部分配置,如雙因數驗證等)
說是特殊用法,實際上是在每一次請求時都會創建一個DbContext、UserManager以及SignInManager放在Owin的環境字典中,那麼意味著整個請求過程中都可以通過Owin來獲取這些實例對用戶進行操作。
1. 使用前準備,封裝DbContext的創建過程:
2. 封裝UserManager創建過程(註:UserManager的創建中還包含了對用戶名、密碼的驗證配置以及一些驗證配置信息):
3. 封裝SignInManager:
SignInManager中依賴的UserManager來自Owin的上下文對象。
另外這裡還對通過用戶信息生成身份信息做了封裝:
4. 在Owin的Startup文件中加入以下代碼,確保在請求時創建這些對象:
需要註意的是CreatePerOwinContext來自Identity的Owin拓展:
而CreatePerOwinContext方法實際上是為Owin管道添加了一個名稱為IdentityFactoryMiddleware的Owin中間件,意思就是上面的三個方法就在Owin管道中插入了三個相同的中間件(但參數不同),以下是IdentityFactoryMiddleware調用的代碼:
5. 修改Controller代碼,在實現用戶註冊、登錄功能時,從Owin的Context中獲取UserManager及SignInManager來實現:
註冊方法,代碼來自預設模板(相比之前的代碼加入了對創建結果的判斷):
登錄方法,代碼來自預設模板(相比之前的代碼加入了對創建結果的判斷):
6. 運行效果:
7. 安裝Identity的漢化包:
從上面的錯誤提示中可以看到英文的提示,它們是通過在Controller中對ModelState信息添加錯誤信息,然後在View中通過Html.ValidationSummary方法顯示出來的(更多與Model相關的內容後續介紹)。
但是由於創建用戶返回的結果信息是英文的,所以顯示也是英文,如果要把它替換成中文,那麼需要安裝漢化包:Microsoft.AspNet.Identity.Core.zh-Hans:
安裝完成運行效果:
註:用戶名密碼的驗證是在創建UserManager的時候配置的:
小結
本文介紹了Owin以及ASP.NET MVC中是如何將Identity集成到Owin中並使用的,另外借鑒ASP.NET MVC模板的代碼改進了之前文章中的用戶註冊、登錄的實現。
參考:
http://owin.org/html/spec/owin-1.0.html#1-overview
https://msdn.microsoft.com/en-us/library/bb470252.aspx
https://docs.microsoft.com/en-us/aspnet/aspnet/overview/owin-and-katana/owin-middleware-in-the-iis-integrated-pipeline
http://katanaproject.codeplex.com/SourceControl/latest#src/Microsoft.Owin.Host.SystemWeb/PreApplicationStart.cs
本文鏈接:http://www.cnblogs.com/selimsong/p/7743112.html