學習ASP.NET Core Blazor程式設計系列二十七——JWT登入(1)

2023-02-26 18:01:07
學習ASP.NET Core Blazor程式設計系列一——綜述
學習ASP.NET Core Blazor程式設計系列八——資料校驗
學習ASP.NET Core Blazor程式設計系列十三——路由(完)
學習ASP.NET Core Blazor程式設計系列十五——查詢
學習ASP.NET Core Blazor程式設計系列二十——檔案上傳(完)
 學習ASP.NET Core Blazor程式設計系列二十二——登入(1)
 

十、JWT介紹

       JWT只是縮寫,全稱則是JSON Web Tokens,是目前流行的跨域認證解決方案,是基於開放標準RFC7519,提供一種身份認證與資訊交換的解決方案,是一種基於JSON的用於在網路上宣告某種主張的令牌(token)。

      由於http的連線是狀態的特性,server端和client是不會記住每個請求是誰發過來的,也不會知道當前傳送請求的使用者是否已經對過身份認證,如果使用者的每一個請求,都要與資料庫通訊進行身份認證,會增加server和資料庫的成本。因此,之前的Web應用一般都會用session或 cookie的方式解決。

      通俗地說,JWT的本質就是一個字串,它是將使用者資訊儲存到一個Json字串中,然後進行編碼後得到一個JWT token,並且這個JWT token帶有簽名資訊,接收後可以校驗是否被篡改,所以可以用於在各方之間安全地將資訊作為Json物件傳輸。JWT的認證流程如下:

 

  1. 使用者第一次登入時,後端核對使用者名稱和密碼,進行身份認證。

         2. 身份認證通過後,生成jwt token,並將user的資訊,包括賬號、登入時間等一些不敏感,不重要的資訊記錄在jwt 中的Payload,將其與JWT Header分別進行Base64編碼拼接後簽名,形成一個JWT Token,形成的JWT Token就是一個如同lll.zzz.xxx的字串。

  1. 後端將jwt token字串作為登入成功的結果返回給client端,client端將返回結果記錄在storage中。
  2. 使用者再次發起請求時,每次請求都要在請求頭中攜帶這個jwt token,server端在收到這個token之後,進行驗證,驗證通過,從jwt中讀取使用者資訊,並執行後續操作;驗證不能過,返回錯誤資訊。
  3. 退出登入時刪除儲存的JWT Token即可。

JWT 結構

        一個token分為3部分:頭部(header)、載荷(payload)、簽名(signature)

        1.頭部(header),JWT頭是一個描述JWT後設資料的JSON物件,alg屬性表示簽名使用的演演算法,預設為HMAC SHA256(寫為HS256);typ屬性表示令牌的型別,JWT令牌統一寫為JWT。最後,使用Base64 URL演演算法將上述JSON物件轉換為字串儲存

        2.載荷(payload),有效載荷部分,是JWT的主體內容部分,是承載訊息具體內容的地方,也是一個JSON物件,包含需要傳遞的資料,需要使用Base64編碼。 JWT指定七個預設欄位供選擇

 

iss(issuer): jwt簽發者
sub(subject): jwt所面向的使用者
aud(audience): 接收jwt的一方, 受眾
exp(expiration time): jwt的過期時間,這個過期時間必須要大於簽發時間
nbf(Not Before): 生效時間,定義在什麼時間之前.
iat(Issued At): jwt的簽發時間
jti(JWT ID): jwt的唯一身份標識,主要用來作為一次性token,從而回避重放攻擊。

     這些預定義的欄位並不要求強制使用。除以上預設欄位外,我們還可以自定義私有欄位,一般會把包含使用者資訊的資料放到payload中,如下例:

 

      3.簽名(signature),簽名雜湊部分是對上面兩部分資料簽名,需要使用base64編碼後的header和payload資料,通過指定的演演算法生成雜湊,以確保資料不會被篡改。首先,需要指定一個金鑰(secret)。該密碼僅僅為儲存在伺服器中,並且不能向用戶公開。然後,使用header中指定的簽名演演算法(預設情況下為HMAC SHA256)根據以下公式生成簽名

        在計算出簽名雜湊後,JWT頭,有效載荷和簽名雜湊的三個部分組合成一個字串,每個部分用.分隔,就構成整個JWT物件

      header和payload可以直接利用base64解碼出原文,從header中獲取雜湊簽名的演演算法,從payload中獲取有效資料

        signature由於使用了不可逆的加密演演算法,無法解碼出原文,它的作用是校驗token有沒有被篡改。伺服器端獲取header中的加密演演算法之後,利用該演演算法加上secretKey對header、payload進行加密,比對加密後的資料和使用者端傳送過來的是否一致。

     注意:secretKey只能儲存在伺服器端,而且對於不同的加密演演算法其含義有所不同,一般對於MD5型別的摘要加密演演算法,secretKey實際上代表的是鹽值

       關於jwt更多資訊,可參考jwt.io的說明。

十一、建立JWT服務

 

  1. 在Visual Studio 2022的解決方案資源管理器中,使用滑鼠右鍵點選「依賴項」,從彈出選單中選擇「管理NuGet程度包」選單項,或是「工具—》NuGet包管理器器—>管理解決方案的NuGet程式包」選單。如下圖。

      

       2. 在搜尋輸入框中輸入「JWT」,然後安裝JWT程式包,如下圖。

      3.在Visual Studio 2022中的NuGet 包管理器控制檯視窗中安裝JWTBearer,由於我這個專案是基於NET6框架的,所以安裝NET6下的最新版本 6.0.11。在PMC中,如下圖。輸入以下命令:

Install-Package Microsoft.AspNetCore.Authentication.JwtBearer -Version 6.0.11

     4. 在Visual Studio 2022中開啟appsettings.json檔案,在此組態檔中新增JWT的設定,參考程式碼如下,注意SecretKey不能設定成太短的純數位,不然要報錯。

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },

  "ConnectionStrings": {
    "BookContext": "Server=.;Database=LeaseBooks;Trusted_Connection=True;MultipleActiveResultSets=true"
  },

  "AllowedHosts": "*",
  "Authentication": {
    "SecretKey": "Blazor!SecKey@[email protected]",

    "Issuer": "JWT.Reg22user@Isskl35",

    "Expires": 10,
    "Audience": "login.Blazor.audit"
  }
}

 

SecretKey,密匙

Issuer,註冊人

Audience,存取人

Expires,到期時間