從零搭建一個IdentityServer——專案搭建

7m魚發表於2021-01-27
  本篇文章是基於ASP.NET CORE 5.0以及IdentityServer4的IdentityServer搭建,為什麼要從零搭建呢?IdentityServer4本身就有很多模板可以直接生成一個可以執行的驗證服務程式,是因為在真實開發過程中很難直接用生成的模板來進行開發,其次是通過生成的方式開發者本身可能會對某些技術細節有所忽略。
   
  本文從以下幾個方面來完成IdentityServer專案搭建:

 建立一個空的Asp.net Core 5.0專案

  通過VS建立一個空的Asp.net core 5.0專案:
  注:此處選擇了Docker支援,需要安裝Docker Desktop,另外第一次通過Docker除錯應用程式需要下載相應的Docker Image和VS的除錯環境,如果映象檔案下載慢,那麼可以變更docker的註冊映象:https://blog.csdn.net/zhangqingmu/article/details/104655635/,如果VS除錯環境下載慢可參考https://blog.csdn.net/lindexi_gd/article/details/106925674手動下載。
  專案啟動後看到以下結果:

新增IdentityServer4元件

  IdentityServer4是一組中介軟體,它實現了OpenID Connect和Oauth2.0協議,來提供身份驗證以及授權服務,新增IdentityServer4僅需要安裝IdentityServer4元件,然後對相關服務和中介軟體進行配置即可:
 

  安裝完成後通過AddIdentityServer方法將相關的服務註冊到容器中,同時這裡返回一個builder用於繼續構建IdentityServer服務,如儲存、快取、加密相關的金鑰等等;

  

  接著將IdentityServer中介軟體新增到Asp.net core的http請求管道中:
  
  注:在新增中介軟體的時候需要注意IdentityServer中介軟體的放置順序,另外在呼叫UseIdentityServer這個方法中還自動新增了身份驗證的中介軟體。

 IdentityServer4資料持久化

  按理來說現在已經可以執行專案了,但是執行的時候出現了無法解析IClientStore型別錯誤:
  

   這個問題的原因在於,IdentityServer4在進行授權時實際上是依賴一系列資料的,這些資料包括Client、Resource、Scope等,所以為了保證授權相關操作能夠完成,需要配置相關資料的儲存服務,IdentityServer4預設提供了測試基於記憶體的資料儲存,但一般只是用於測試目的:

   

   關於資料持久化,在.net技術棧中可以想到的就是Entity Framework,同時IdentityServer4提供了名為:IdentityServer4.EntityFramework的包,它包含了相關的實體型別(IdentityServer4.EntityFramework.Storage)以及EF的DbContext。所以引入IdentityServer4.EntityFramework包就可以實現基於EF的資料持久化,另外也可以自己實現。

  

 

   上圖中可以看到IdentityServer4關於EF的包有2個,但是實際上安裝IdentityServer4.EntityFramework就包含Storage這個包了:

  

   安裝完成之後,我們可以在IdentityServer4.EntityFramework.Storage包中找到以下兩個DbContext型別:

  ConfigurationDbContext :
  PersistedGrantDbContext :
   
  
  為了EF能夠正常工作需要根據資料庫型別安裝相應的EF資料庫提供器(本例使用的是Mariadb):

   然後就可以對IdentityServer的儲存進行配置了:

  

  以上主要是對資料庫連結字串、資料庫版本、字符集以及資料庫遷移程式集進行配置,需要注意的是在對資料庫進行遷移的時候預設使用DbContext所在的程式集,而IdentityServer4提供的DbContext位於IdentityServer4.EntityFramework.Storage包裡面,所以為了能夠確保遷移檔案正常生成,所以需要將Startup所在的程式集設為遷移程式集(注:更適合的方式是專門建立一個資料庫遷移專案來作為遷移程式集,這樣資料庫遷移的相關內容可以單獨維護)。

  另外還需要注意的是資料庫連結字串,在開發時可能資料庫安裝在本地可以使用127.0.0.1,但是如果在dorcker中除錯的話127.0.0.1無法連結到資料庫。
  完成配置後即可將資料庫結構遷移到資料庫中,首先需要安裝EF的工具:
  工具描述,相關命令及引數可參考文件https://docs.microsoft.com/en-us/ef/core/cli/powershell
  
  執行命令(引數o表示遷移檔案輸出路徑,因為存在多個DbContext以及需要多個資料遷移,所以分開儲存):
  Add-Migration initPersistedGrantDb -c PersistedGrantDbContext -o Migrations/IdentityServer/PersistedGrantDb
  Add-Migration initConfigurationDb -c ConfigurationDbContext -o Migrations/IdentityServer/ConfigurationDb

  注:-c和-o分別是-Context 和-OutputDir 的簡寫,在引數沒有二義性時可以使用簡寫。

  生成的檔案:
  

  執行資料庫更新命令後,資料庫將完成建立:

  Update-Database -Context PersistedGrantDbContext
  Update-Database -Context ConfigurationDbContext
  

  資料庫也就建立好了:

  

   啟動程式,並訪問https://localhost:55006/.well-known/openid-configuration即可看到以下內容,證明IdentityServer4已經成功啟動了:

  

  但是由於資料庫中還沒有任何資料,所以還無法進行授權操作,因為資料庫中還沒有任何資料,這裡簡單的把IdentityServer4模板建立的建立初始資料程式碼引入,並完成資料建立:
  

   注:關於IdentityServer4的預設資料可通過命令“dotnet new -i IdentityServer4.Templates”先安裝IdentityServer4相關模板,然後使用“dotnet new is4ef”命令來建立,具體參考文件:https://identityserver4.readthedocs.io/en/latest/quickstarts/5_entityframework.html

  在啟動引數中包含“/seed”時建立資料,關於啟動引數,可以直接執行程式時新增,如dotnet .\IdentityServer.dll /seed,或者通過VS中設定除錯引數進行除錯(資料生成後刪除):
  

配置IdentityServer4證照

  執行程式,通過測試資料中的client及其密碼嘗試獲取access token:

  

  啊哦,出錯了,未配置簽名證照,無法建立Jwt token,簡單來說就是為了保證token的簽名和驗證,需要配置一個數字簽名證照,關於證照配置可參考文件:https://identityserver4.readthedocs.io/en/latest/topics/startup.html#key-material
  為了方便,使用開發證照進行測試:
  

   新增程式碼後再次執行程式,就能夠生成Access Token 了:

建立一個基於Jwt身份驗證的WebApi專案

  最後通過VS新建一個預設的WebApi專案來驗證一下是否能夠通過access_token訪問受保護資源。
  在新建的專案中新增基於Jwt bearer的驗證服務:
  
  同時新增身份驗證中介軟體:
  

   設定API的授權訪問:

  

  獲取token後訪問受保護API:
  

   成功訪問,但是這裡有個小細節需要注意一下,就是當獲取到access token後,在token的有效期內,哪怕是把IdentityServer關閉,也能使用token正常訪問受保護資源,換句話說access token頒發後就與IdentityServer無關了,以上內容實際上是使用Asp.Net core 5.0以及IdentityServer4實現了一個基於客戶端證照(Client Credentials)的Oauth2.0授權流程,但IdentityServer提供的內容不僅於此,後續文章將會對該IdentityServer繼續完善,使其成為一個功能完善的身份驗證服務。

小結 

  本篇文章從一個空專案開始,不斷往裡面新增元件和程式碼,搭建了一個基於IdentityServer4的身份驗證伺服器,並且到目前為止已經實現了IdentityServer4的相關資料持久化,並且能夠通過Client_Credentials等方式獲取Access Token,實現了基於Jwt的身份驗證,這一切實際上都是基於Oauth2.0協議的,關於Oauth2.0可以參考文章:https://www.cnblogs.com/selimsong/p/8037717.html
  但IdentityServer4是一個實現OpenIDConnect協議的身份驗證/授權服務,更多內容將在後續文章中介紹。
參考:
 

相關文章