JWT:擁有我,即擁有權力

来源:https://www.cnblogs.com/ISangyu/archive/2022/09/26/16730518.html
-Advertisement-
Play Games

Hi,這裡是桑小榆。 上篇文章中,我們一起探討了 OAuth 協議的原理以及授權認證流程,本次我們一起探討 jwt 令牌作為授權協議的傳輸介質。 OAuth協議規範了幾個參與角色的授權標準,安全可控的授予第三方應用,第三方應用獲取到用戶授予的許可權之後,與資源伺服器進行交互。那麼在進行交互的時候,必然 ...


 

Hi,這裡是桑小榆。

 

上篇文章中,我們一起探討了 OAuth 協議的原理以及授權認證流程,本次我們一起探討 jwt 令牌作為授權協議的傳輸介質。

OAuth協議規範了幾個參與角色的授權標準,安全可控的授予第三方應用,第三方應用獲取到用戶授予的許可權之後,與資源伺服器進行交互。那麼在進行交互的時候,必然需要一種傳輸介質,且需要攜帶用戶身份的信息,使得伺服器之間能夠識別並認證。這個傳輸的介質就是我們此次探討的 jwt。

jwt,全稱 Json Web Token,也就是日常說的 token 令牌。它是通過數字簽名的方式,以 json 對象為載體,在不同服務終端之間安全傳輸信息。

我們可以看到jwt的定義,它具有和 json 一樣的特性,非常輕量的傳輸方式,且易於人閱讀和編寫,利於機器的解析和生成。

它像我們的居民身份證一樣,一旦相關權威部門識別你是合法公民且會頒發一個適用於本土的證件,通過這個證件可以任意出入需要出示證件的地方。那麼jwt也是一樣,在伺服器認證你的合法用戶身份之後,會生成一個json對象,發送給用戶,例如:

{
    "姓名": "桑小榆",
    "角色": "管理員",
    "到期時間": "2022年10月1日 10點10分"
}

之後,用戶每需要與伺服器通訊的時候,攜帶具有身份信息的json。伺服器完全只需要驗證用戶攜帶的身份信息。

當然,用戶信息不會以明文的方式攜帶,不然很容易被不法分子截獲進行篡改,那這個令牌就變得無意義了。但凡頒發任何具備流通的信息,都需要具備防偽標識。例如身份證,系統架構師資格證,人民幣等都具備複雜的防偽信息。

那 jwt 在生成的時候,通常是加上簽名來防止篡改的。形成一個標準的 jwt 格式如下:

▲圖/ jwt解析組成部分

 

我們可以看到左邊生生簽名之後的 jwt 格式是很長得一串字元組成,中間由(.)隔開分成三部分。

我們看到右邊解析之後,是jwt的組成格式。

Header     頭部
Payload    載荷
Signature  簽名

以上組成jwt格式為:Header.Payload.Signature

那麼我們將依次探討這三部分。

Header頭部

header部分是一個json對象,描述jwt的一些元數據,也就是屬性信息。通常格式如下:

{
    "alg": "HS256",
    "typ": "JWT"

上面的代碼中,alg屬性表示採用簽名的演算法(algorithm),預設是 hmac sha256,寫成 hs256。這裡通常有幾種比較常用的簽名演算法rs256,hs256,base64

rs256(帶有sha-256的 rsa 簽名)是一種非對稱演算法,它使用公鑰/私鑰對:身份提供者擁有用於生成簽名的私鑰(秘密)密鑰,而 jwt 的消費者獲得公鑰驗證簽名。由於與私鑰相反,公鑰不需要保持安全,因此大多數身份提供者都可以讓消費者輕鬆獲取和使用(通常通過元數據 url)。

hs256(帶有 sha-256 的hmac)涉及散列函數和一個密鑰的組合,該密鑰在兩方之間共用,用於生成用作簽名的散列。由於生成簽名和驗證簽名都使用相同的密鑰,因此必須註意確保密鑰不被泄露。

 

typ屬性表示這個令牌(token)的類型(type),jwt 令牌統一寫為jwt

最後,將上面的 json 對象使用 base64url 演算法轉成字元串。

Payload 載荷

payload 部分也是一個 json 對象,用來存放實際需要傳遞的數據,通常包含一些簽發的信息。jwt 規定了7個官方欄位,供選用。

iss (issuer): jwt簽發者.

sub (subject): jwt所面向的用戶.

aud (audience): 接收jwt的一方.

exp (expiration time): jwt的過期時間,這個過期時間必須要大於簽發時間.

nbf (Not Before): 定義在什麼時間之前,該jwt都是不可用的.

iat (Issued At): jwt的簽發時間.

jti (JWT ID): jwt的唯一身份標識,主要用來作為一次性token,從而迴避重放攻擊.

當然除了官方定義的七種之外,還可以自己定義一些私有欄位。例如上圖 jwt 格式中的 payload 格式,就是是自定義了一些私有欄位。

{
  "sub": "1234567890",
  "name": "桑小榆呀",
  "iat": 1516239022

註意,jwt 預設是不加密的,任何人都可以讀到,所以不要把私密信息放在這個部分。所以,payload 部分要使用 base64url 演算法轉成字元串。

Signature 簽名

signature 部分是對前header和payload的簽名,防止數據篡改。

首先,需要指定一個256位的密鑰(secret)。這個密鑰只有伺服器才知道,不能泄露給用戶。然後,使用 header 裡面指定的簽名演算法(預設是 hmac sha256),按照下麵的公式產生簽名。

HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret

算出簽名以後,把 header、payload、signature 三個部分拼成一個字元串,每個部分之間用點(.)分隔,就可以返回給用戶。

Base64Url 演算法

 

我們在上面的文章中也多次提到,header和payload部分需要使用base64url演算法。base64url演算法跟base64演算法基本類似,但也有一些不同。

jwt作為一個token令牌,有些使用場景可能會用到url,例如 https://jwt.io/?token=xxx。加密流程首先會對url的明文進行加密,其次在base64加密的基礎上,會對url裡面特殊字元進行處理:=被省略、+替換成-/替換成_ 。這就是base64url加密演算法。

JWT 使用

 

我們探討完了 jwt 的組成之後,回歸到使用上。在身份驗證中,客戶端使用身份憑據成功登錄時,將返回一個 Token 令牌。由於令牌是憑據,因此必須非常小心以防止出現安全問題。通常情況下不應該將令牌保留超過所需的時間。

 

雖然我們可以將Token存儲在Cookie和localStorage當中,進行自動發送。但會缺乏安全性,和跨域的問題。更好的做法是在authorization標頭中使用bearer模式。標頭的內容應如下所示:

Authorization: Bearer <token>

如果令牌在authorization標頭中發送,則跨域資源共用 (CORS) 不會成為問題,因為它不使用 cookie。配合https傳輸也能大大提高了安全性。

▲圖/ jwt簡易授權流程

 

JWT 特點

 

最後我們總結 jwt 的幾個特點:

1.  jwt 預設是不加密,但也是可以加密的。生成原始 Token 以後,可以用密鑰再加密一次。

2. jwt 不加密的情況下,不能將秘密數據寫入 jwt 。

3. jwt 不僅可以用於認證,也可以用於交換信息。有效使用 jwt ,可以降低伺服器查詢資料庫的次數。

4. jwt 的最大缺點是,由於伺服器不保存 session 狀態,因此無法在使用過程中廢止某個 token,或者更改 token 的許可權。也就是說,一旦 jwt 簽發了,在到期之前就會始終有效,除非伺服器部署額外的邏輯。

5. jwt 本身包含了認證信息,一旦泄露,任何人都可以獲得該令牌的所有許可權。為了減少盜用,jwt 的有效期應該設置得比較短。對於一些比較重要的許可權,使用時應該再次對用戶進行認證。

6. 為了減少盜用,jwt 不應該使用 http 協議明碼傳輸,要使用 https 協議傳輸。

我們一起探討完了 jwt 相關知識。下篇我們將以代碼實操的方式來演示 jwt 的生成以及使用,並且配合 oidc 一套標準的授權流程。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 函數 1.字元串函數 #(1)add() 對兩個數組的元素進行字元串連接 import numpy as np print(np.char.add(["xiaodu"],["good"])) print(np.char.add(["xiaodu","dudu"],["good","nice"])) ...
  • 事情是這樣的:今天晚上,女朋友讓我十二點催她睡覺。 不過,可是我實在太困了,熬不下去…… 是吧?女朋友哪有睡覺重要? 但,女朋友的命令,我是不敢違抗的…… 但是睡覺也不能缺! 這時候我們該怎麼辦呢?是時候讓Python登場了! Python登場這次我們來做一個自動發送微信的程式,在深夜十二點的時候給 ...
  • 1、初衷 開發中經常需要做一些介面的簽名生成和校驗工作,最開始的時候都是每個介面去按照約定單獨實現,久而久之就變的非常難維護,因此就琢磨怎麼能夠寫了一個比較通用的簽名生成工具。 2、思路 採用鏈式調用的方式,使得簽名的步驟可以動態拼湊組合。 3、直接看效果 //設置數據源 var signSourc ...
  • .Net7 的到來的同時,也帶來了 C# 11,而令我最期待的就是 C# 11 的 原始字元串了,當我知道這個的時候,簡直比過年還要開心。 非原始字元串 首先我們看看現在寫字元串的方式 var str = @" 雪莉:""有人在嗎?"" 神樂:""他們有事出去了,你有什麼困擾呢? 萬事屋神樂為您服務 ...
  • 1. 發佈打包前端管理平臺(ant-design-vue) 2. 發佈打包後端(.NET6-WebApi) .NET6 webAPI orm: free sql 資料庫:mysql5.7 3. 發佈打包H5端(uni) 播放器使用: import Player from 'xgplayer'; // ...
  • 相關下載: 資料庫的負載均衡-示例代碼(dp1-DbBalance.rar) 資料庫的負載均衡-示例代碼(dp1-DbBalance.rar) 支持.Net/.Net Core/.Net Framework 為了演示資料庫的負載均衡(Load Balance),我們先創建三個資料庫,它們的名字分別為 ...
  • 用戶可以在 Windows 10 和 Windows 11 電腦上使用 winget 命令行工具來發現、安裝、升級、刪除和配置應用程式。 此工具是 Windows 程式包管理器服務的客戶端介面。 以下是 Windows 包管理器上可用的 .NET 版本列表: .NET VersionSupport ...
  • 實現原理 當我們new一個上下文DbContext 後, 每次執行CURD方式時 ,都會依次調用OnConfiguring(),OnModelCreating()兩個方法。 OnConfiguring() 我們將用來替換一些服務實現,以支持分表的工作 OnModelCreating() 我們將用來重 ...
一周排行
    -Advertisement-
    Play Games
  • 概述:在C#中,++i和i++都是自增運算符,其中++i先增加值再返回,而i++先返回值再增加。應用場景根據需求選擇,首碼適合先增後用,尾碼適合先用後增。詳細示例提供清晰的代碼演示這兩者的操作時機和實際應用。 在C#中,++i 和 i++ 都是自增運算符,但它們在操作上有細微的差異,主要體現在操作的 ...
  • 上次發佈了:Taurus.MVC 性能壓力測試(ap 壓測 和 linux 下wrk 壓測):.NET Core 版本,今天計劃準備壓測一下 .NET 版本,來測試並記錄一下 Taurus.MVC 框架在 .NET 版本的性能,以便後續持續優化改進。 為了方便對比,本文章的電腦環境和測試思路,儘量和... ...
  • .NET WebAPI作為一種構建RESTful服務的強大工具,為開發者提供了便捷的方式來定義、處理HTTP請求並返迴響應。在設計API介面時,正確地接收和解析客戶端發送的數據至關重要。.NET WebAPI提供了一系列特性,如[FromRoute]、[FromQuery]和[FromBody],用 ...
  • 原因:我之所以想做這個項目,是因為在之前查找關於C#/WPF相關資料時,我發現講解圖像濾鏡的資源非常稀缺。此外,我註意到許多現有的開源庫主要基於CPU進行圖像渲染。這種方式在處理大量圖像時,會導致CPU的渲染負擔過重。因此,我將在下文中介紹如何通過GPU渲染來有效實現圖像的各種濾鏡效果。 生成的效果 ...
  • 引言 上一章我們介紹了在xUnit單元測試中用xUnit.DependencyInject來使用依賴註入,上一章我們的Sample.Repository倉儲層有一個批量註入的介面沒有做單元測試,今天用這個示例來演示一下如何用Bogus創建模擬數據 ,和 EFCore 的種子數據生成 Bogus 的優 ...
  • 一、前言 在自己的項目中,涉及到實時心率曲線的繪製,項目上的曲線繪製,一般很難找到能直接用的第三方庫,而且有些還是定製化的功能,所以還是自己繪製比較方便。很多人一聽到自己畫就害怕,感覺很難,今天就分享一個完整的實時心率數據繪製心率曲線圖的例子;之前的博客也分享給DrawingVisual繪製曲線的方 ...
  • 如果你在自定義的 Main 方法中直接使用 App 類並啟動應用程式,但發現 App.xaml 中定義的資源沒有被正確載入,那麼問題可能在於如何正確配置 App.xaml 與你的 App 類的交互。 確保 App.xaml 文件中的 x:Class 屬性正確指向你的 App 類。這樣,當你創建 Ap ...
  • 一:背景 1. 講故事 上個月有個朋友在微信上找到我,說他們的軟體在客戶那邊隔幾天就要崩潰一次,一直都沒有找到原因,讓我幫忙看下怎麼回事,確實工控類的軟體環境複雜難搞,朋友手上有一個崩潰的dump,剛好丟給我來分析一下。 二:WinDbg分析 1. 程式為什麼會崩潰 windbg 有一個厲害之處在於 ...
  • 前言 .NET生態中有許多依賴註入容器。在大多數情況下,微軟提供的內置容器在易用性和性能方面都非常優秀。外加ASP.NET Core預設使用內置容器,使用很方便。 但是筆者在使用中一直有一個頭疼的問題:服務工廠無法提供請求的服務類型相關的信息。這在一般情況下並沒有影響,但是內置容器支持註冊開放泛型服 ...
  • 一、前言 在項目開發過程中,DataGrid是經常使用到的一個數據展示控制項,而通常表格的最後一列是作為操作列存在,比如會有編輯、刪除等功能按鈕。但WPF的原始DataGrid中,預設只支持固定左側列,這跟大家習慣性操作列放最後不符,今天就來介紹一種簡單的方式實現固定右側列。(這裡的實現方式參考的大佬 ...