從零搭建一個IdentityServer——集成Asp.net core Identity
- 2021 年 1 月 28 日
- 筆記
- .NET Core, Asp.Net Core, asp.net core identity, Identity, IdentityServer, IdentityServer4, 跨平台
前面的文章使用Asp.net core 5.0以及IdentityServer4搭建了一個基礎的驗證伺服器,並實現了基於客戶端證書的Oauth2.0授權流程,以及通過access token訪問被保護資源,本文將繼續完善IdentityServer實現與Identity組件的集成,可使用Identity的用戶來完成授權。
- 集成Asp.net core Identity與元包(MetaPackage)
- Asp.net core Identity數據持久化
- Asp.net core Identity UI
- Asp.net core Identity與IdentityServer4集成
- 小結
集成Asp.net core Identity
在軟體領域中只要提到身份驗證就能想到登錄,而登錄往往與用戶名和密碼相關聯,IdentityServer4或者說OAuth2.0和OpenIDConnect也是一樣的,它需要用戶數據來支援完成相關的驗證及授權操作,下面我們就先來實現IdentityServer4的用戶數據接入及與用戶數據相關的授權流程。
首先為IdentityServer添加Asp.Net core Identity模組:
Asp.net core Identity是Asp.net core的身份驗證組件,它不僅包含了身份驗證所需的數據及數據持久化支援,另外還提供了用戶管理、登錄管理等一系列的服務和UI,在創建新的Asp.net core mvc或api項目時,如果勾選身份驗證選項就會默認包含該組件,但是由於文本中的例子是從零開始的,所以Identity組件也需要手動添加。
在添加Identity之前還有一個概念需要再說一下就是metapackege(元包,具體參考://natemcmaster.com/blog/2018/08/29/netcore-primitives-2/),它實質上是一組共享庫,提供了.net core和asp.net core應用的基礎運行時和基礎功能,在創建項目時默認會依賴相應.net core版本的元包,而元包共享的程式集實際上在dotnet的安裝目錄的shared目錄下,元包的好處就是在框架發布時,發布文件就不需要包含元包內容,減少發布文件大小:
而Asp.net core 5.0應用程式包含兩個元包:
其中Microsoft.AspNetCore.App中包含了Identity的基礎組件:
基礎組件中已經包含了Identity的基礎組件,如IdentityUser等相關的實體以及相關的服務類型/介面,所以換句話說使用Identity功能僅需要完成數據持久化及UI即可。
Asp.net core Identity數據持久化
EF core是.net core下面的首選數據持久化框架,所以同樣的identity也提供了基於EF core的數據持久化組件,添加基於EF的Identity數據持久化組件:
同時為了方便後續的擴展,新建一個ApplicationUser繼承於IdentityUser和ApplicationDbContext繼承於IdentityDbContext<ApplicationUser>:
添加Identity的數據上下文及identity服務:
添加資料庫遷移程式碼並更新到資料庫:
Add-Migration initIdentityDb -c ApplicationDbContext -o Migrations/IdentityServer/IdentityDb
Update-Database -Context ApplicationDbContext
Asp.net core Identity UI
Identity的UI是一個Razor的類庫,換句話說就是頁面文件被包含在類庫裡面了,如果要對UI進行修改可以通過VS的構建程式構建(VS Code可參考文檔://docs.microsoft.com/en-us/aspnet/core/security/authentication/scaffold-identity?view=aspnetcore-5.0&tabs=netcore-cli#scaffold-identity-into-an-empty-project):
在對話框中選擇「標識(Identity)」中的「標識(Identity)」選項:
在標識對話框中勾選「替代所有文件」,布局文件沒有留空即可,最後選擇Identity的DbContext即可:
添加Razor服務、靜態文件處理中間件(訪問js等文件)及Razor終結點映射:
訪問登錄地址://localhost:55002/Identity/Account/Login
到目前為止identity的資料庫和UI都已經添加到項目中並且可以運行了,但是還存在一些問題,如默認的Identity UI相關功能依賴IEmailSender組件等等,同時還需要與IdentityServer4集成,其登錄、註冊、登出等基礎功能需要根據IdentityServer4本身的一些需求進行修改。
Asp.net core Identity與IdentityServer4集成
下面就進入IdentityServer4與Asp.net core Identity的集成工作,首先先添加IdentityServer4.AspNetIdentity組件:
然後通過IIdentityBuilder向容器中添加相關服務:
最後對修改一下Identity的註冊程式碼,將與IEmailSender有關的程式碼注釋掉(註:默認生成程式碼中包含郵件發送邏輯,但是沒有EmailSender的實現,除了注釋相關程式碼外也可以實現一個IEmailSender並註冊到容器中來解決問題):
啟動應用,訪問註冊頁面註冊用戶://localhost:55002/Identity/Account/Register
註冊成功後,在資料庫中為相應的client資訊手動添加一條基於用戶名密碼的Grant Type(password),即可使用註冊的用戶來通過password的方式獲取access token了:
以下是通過剛註冊用戶名密碼獲得的access token:
對上面的access token解碼後可以看到它的payload部分包含以下資訊(sub使用了用戶的Id):
小提示:在IdentityServer4中獲取Token時會根據請求對攜帶的Client資訊以及相關參數進行驗證,本例中如果Client不支援Password的Grant Type,那麼會導致不支援相應的授權類型而導致無法正確獲得Access Token,遇到無法正確獲得Access Token或者一些驗證錯誤的時候可以在調試模式下查看IdentityServer的輸出,裡面會包含相關授權成功/失敗的資訊。
小結
本篇文章通過集成asp.net core identity組件實現了用戶管理,包括註冊、登錄等,並且實現了通過註冊的用戶,基於Oauth2.0的用戶名密碼模式(password grant type)來獲取到Access Token,但就目前為止本系統文章所實現的、演示的IdentityServer功能仍舊是基於Oauth2.0協議,從下一篇文章開始就會開始介紹OpenIDConnect(oidc)相關的內容,此外現階段實現的Identity登錄也僅僅只是Identity本身的內容,針對OpenIDConnect或者說IdentityServer4它還有一些額外的操作,如事件、授權同意等等,這些內容也會在後續文章中不斷完善。
參考:
//natemcmaster.com/blog/2018/08/29/netcore-primitives-2/
本文鏈接://www.cnblogs.com/selimsong/p/14338193.html