.NET Core認證管理解析
.NET Core中的認證管理解析
#0x00 問題來源
在新建.NET Core的Web專案時選擇「使用個人使用者帳號」就可以建立一個帶有使用者和權限管理的項目,已經準備好了使用者註冊、登入等很多頁面,也可以使用AuthorizeAttribute進行各種權限管理,看起來似乎很方便。不過產生的程式碼都替我做了些什麼我一團霧水。看了下生成的數據表,功能也挺複雜的。實際上我需要的只是基於使用者和角色的認證管理,而且使用者資料是使用現有的庫,但使用.NET Core自帶的認證元件必須依賴EF,表的結構也很多對不上,所以學習了下自帶的認證元件的實現,然後自己寫了個認證服務替換了Identity元件,同時Cookie管理使用自帶的Cookie#中間件 、可以使用AuthorizeAttribute進行認證。複雜的需求還沒遇到,所以就學到這裡了。這篇部落格主要討論最簡單情況下的的基於使用者和角色的認證。關於.NET Core自備認證組件的一些基本用法,可以參考http://www.php.cn/。
0x01 .NET Core中的認證管理
提到認證管理,首相想到的就是用戶的註冊、登入、登出以及給用戶添加/刪除角色等功能。其中使用者訊息,角色資訊等都是保存在資料庫中的。所以主要包含資料庫操作和登入業務邏輯兩部分。在登入業務邏輯層面,.NET Core主要透過三個比較核心的類別UserManager、RoleManager、SigninManager進行管理(在Microsoft.AspNetCore.Identity組件)。其中:
UserManager主要負責使用者的認證、註冊、修改、刪除以及與使用者相關的角色、令牌、宣告等的管理。
RoleManager負責角色、角色相關宣告的管理。
SigninManager負責登入、登出等相關操作。在涉及到使用者操作(如登陸時使用者驗證)會呼叫UserManager進行操作。
這三個核心類別在操作資料庫時,使用資料庫層面的UserStore、RoleStore進行操作(在Microsoft.AspNetCore.Identity.EntityFrameworkCore組件)。業務關係如下圖所示:
我們在開發認證相關功能時使用這三個核心類別即可滿足大多數需求。我們在使用這幾個核心類別的物件時都是透過依賴注入取得的,那麼這些相關的依賴是什麼時候注入的呢?在Startup的ConfigureServices方法中有AddIdentity擴充方法,就是在這個方法中加入了所有所需的依賴。
0x02 登入與登出
了解了Identity元件的整體分工後,再來看登入和註銷的操作的部分細節。登入和登出過程主要由SigninManager負責,的先來看看登入的過程:
#
##登入後Response的Header中包含了Set-Cookie,Cookie的Key#需要和Cookie中間件中設定的要解密的Cookie的Key一致,在截圖中這個Cookie的Key是IdentityCookie。設定Cookie的同時返回302重定向到登入頁面。
#
重定向到登陸頁面時,請求中已經帶有設定的Key為IdentityCookie的Cookie了。
註銷程序比較簡單,呼叫HttpContext.Authentication.SignOutAsync方法即可登出,此時會為HttpContext.Response加上Set-Cookie,但內容為空。
0x03 透過Cookie辨識使用者
.NET Core中透過CookieAuthenticationMid#dleware這個中間件識別HttpContext中認證相關的Cookie,從而新增使用者的驗證和授權資訊。最關鍵的是ClaimsPrincipal對象,它記錄用戶的認證和授權資訊(除此之外當然也可以包含其它你需求的任意資訊),從上面登入過程可以看到,登入成功後用戶認證和授權資訊儲存至ClaimsPrincipal物件(實際上對於這條Cookie鍵值對中的認證資訊儲存為ClaimsIdentity,一個ClaimsPrincipal可以包含多個ClaimsIdentity),然後在HttpContext.Response的Headers中加入Set-Cookie,Key為Cookie中間件中指定的CookieName,Value就是這個物件加密後的字串。以後的HttpContext都會帶有這個Cookie,Cookie中間件會把符合這個CookieName的Cookie取出來,解密並還原為ClaimsPrincipal對象,並把HttpContext.User設定為這個物件。後面MVC中間件在路由到對應Controller和Action#的時候就可以根據Authorize特性中指定的認證和角色在HttpContext.User中檢查,不滿足檢查則跳到對應頁面。因此要注意的就是一定要把Cookie中間件放在MVC中間件之前。
這裡要特別說一下ClaimsPrincipal。一個ClaimsPrincipal對象包含了一個或多個ClaimsIdentity對象,一個ClaimsIdentity對像一般來說對應著一個Cookie中某鍵值對(個人理解)。 Cookie中間件和ClaimsIdentity是透過AuthenticationScheme連結起來的。後面我們在寫自己的認證服務時,也是把Cookie中間件的AuthenticationScheme和創建的ClaimsIdentity一致。所以更準確地說是ClaimsIdentity包含了使用者認證和權限的聲明,而ClaimsPrincipal可以包含多個ClaimsIdentity。當管道中存在多個Cookie中間件時,透過AuthenticationScheme進行區分。
在ClaimsIdentity中除了AuthenticationScheme外還有兩個比較重要的屬性,UserType和RoleType,其中UserType指定了使用者驗證類型,RoleType指定可角色驗證類型。意思是如果我指定了RoleType為”RoleName”,那麼在進行角色認證時就會尋找Claims中所有的Type為”RoleName”的值,並檢查其中是否包含了Authorize中指定的RoleName。不過.NET Core中自備了ClaimTypes,可以直接使用。例如角色類型就是ClaimTypes.Role。如果新增角色時使用的自帶的ClaimTypes.Role,那麼在建立ClaimsIdentity時就不需要顯示指定RoleType了,預設角色認證就是使用ClaimTypes.Role。
關於Cookie中間件的添加,是透過Startup中Configure方法中的app.UseIdentity擴展方法實現的。這個擴充方法其實加入了多種Cookie辨識方式。在後面我在寫自己的用戶認證管理時只用一種。
0x04 自己寫使用者認證管理
##了解了使用者認證的過程,我們可以自己寫認證管理來取代Identity元件了,同樣分為資料庫操作和認證業務邏輯。資料庫相關就不多說了,都寫到了IdentityRepository類,只有很簡單的資料操作。為了方便使用了Dapper,資料庫用的Sqlite。程式在啟動時會檢查資料庫表,沒有會自動建立空表。
認證服務也比較簡單就都寫到了IdentityService類,提供了註冊和登入操作,註銷太簡了直接寫在了Action裡。為了方便沒有提供角色管理頁面,如果要測試角色認證功能,需要手動去資料庫新增Role,然後在UserRoles中為使用者新增Role。
#只是為了測試,邏輯上很多問題,例如使用者密碼明文儲存。重點看過程:)
0x05寫在最後
第一次接觸Web應用程式,很多概念都不是很了解。就拿Cookie認證用戶來說,我之前的只知道透過Cookie辨識用戶,一直以為是收到Cookie後再從資料庫或快取查出對應的權限資訊。不過看了自帶的Cookie中間件代碼後才知道認證資訊是直接存在Cookie中的,這樣只要解密後反序列化就可以了。 Identity這個程式集涉及了很多其它程序集(Security、HttpAbstraction等等),看得我很暈,最後總算搞明白了一些,很多細節也沒去深究,文中內容有的基於代碼,有的基於個人理解,有錯誤希望大家嘴下留情。
以上是.NET Core認證管理解析的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

在 C 語言中,char 類型在字符串中用於:1. 存儲單個字符;2. 使用數組表示字符串並以 null 終止符結束;3. 通過字符串操作函數進行操作;4. 從鍵盤讀取或輸出字符串。

C 語言中符號的使用方法涵蓋算術、賦值、條件、邏輯、位運算符等。算術運算符用於基本數學運算,賦值運算符用於賦值和加減乘除賦值,條件運算符用於根據條件執行不同操作,邏輯運算符用於邏輯操作,位運算符用於位級操作,特殊常量用於表示空指針、文件結束標記和非數字值。

C語言中通過轉義序列處理特殊字符,如:\n表示換行符。 \t表示製表符。使用轉義序列或字符常量表示特殊字符,如char c = '\n'。注意,反斜杠需要轉義兩次。不同平台和編譯器可能有不同的轉義序列,請查閱文檔。

多線程和異步的區別在於,多線程同時執行多個線程,而異步在不阻塞當前線程的情況下執行操作。多線程用於計算密集型任務,而異步用於用戶交互操作。多線程的優勢是提高計算性能,異步的優勢是不阻塞 UI 線程。選擇多線程還是異步取決於任務性質:計算密集型任務使用多線程,與外部資源交互且需要保持 UI 響應的任務使用異步。

在 C 語言中,char 和 wchar_t 的主要區別在於字符編碼:char 使用 ASCII 或擴展 ASCII,wchar_t 使用 Unicode;char 佔用 1-2 個字節,wchar_t 佔用 2-4 個字節;char 適用於英語文本,wchar_t 適用於多語言文本;char 廣泛支持,wchar_t 依賴於編譯器和操作系統是否支持 Unicode;char 的字符範圍受限,wchar_t 的字符範圍更大,並使用專門的函數進行算術運算。

在 C 語言中,char 類型轉換可以通過:強制類型轉換:使用強制類型轉換符將一種類型的數據直接轉換為另一種類型。自動類型轉換:當一種類型的數據可以容納另一種類型的值時,編譯器自動進行轉換。

char 和 unsigned char 是存儲字符數據的兩種數據類型,主要區別在於處理負數和正數的方式:值範圍:char 有符號 (-128 到 127),unsigned char 無符號 (0 到 255)。負數處理:char 可以存儲負數,unsigned char 不能。位模式:char 最高位表示符號,unsigned char 無符號位。算術運算:char 和 unsigned char 作為有符號和無符號類型,其算術運算方式不同。兼容性:char 和 unsigned char

char 數組在 C 語言中存儲字符序列,聲明為 char array_name[size]。訪問元素通過下標運算符,元素以空終止符 '\0' 結尾,用於表示字符串終點。 C 語言提供多種字符串操作函數,如 strlen()、strcpy()、strcat() 和 strcmp()。
