用Java解碼JWT令牌

1.概述

REST API安全性中經常使用JSON Web令牌(JWT)。儘管可以通過諸如Spring Security OAuth之類的框架來解析令牌,但我們還是希望以自己的代碼處理令牌。

在本教程中,我們將解碼並驗證JWT的完整性

2. JWT令牌的結構

首先,讓我們了解一下JWT令牌的結構:

  • 標頭
  • payload (通常稱為主體)
  • 簽名

簽名是可選的。有效的JWT令牌只能由標頭和有效負載部分組成。但是,我們使用簽名部分來驗證標頭和有效負載中安全授權的內容。

這些部分錶示為以句點(‘.')分隔的base64編碼字符串。通過設計,任何人都可以解碼JWT令牌並讀取標頭和有效負載部分的內容。但是,我們需要訪問用於創建簽名的密鑰以驗證令牌的完整性。

最常見的是,JWT包含用戶的“聲明”。這些代表有關用戶的數據,API可以使用這些數據來授予權限或跟踪提供令牌的用戶。解碼令牌可以使應用程序使用數據,而驗證則可以使應用程序相信JWT是由受信任的源生成的。

讓我們看看如何在Java中解碼和驗證令牌。

3.解碼JWT令牌

我們可以使用內置的Java函數解碼令牌。

首先,讓我們將令牌分為幾個部分:

String[] chunks = token.split("\\.");

我們應該注意,傳遞給String.split的正則表達式使用轉義的'.'避免使用'。'的字符。意思是“任何字符”。

我們的chunks數組現在應該具有2或3個與JWT的部分相對應的元素。

接下來,讓我們使用base64解碼器對標頭和有效負載部分進行解碼:

Base64.Decoder decoder = Base64.getDecoder();



 String header = new String(decoder.decode(chunks[0]));

 String payload = new String(decoder.decode(chunks[1]));

讓我們使用JWT令牌運行以下代碼(我們可以在線解碼以比較結果):

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkJhZWxkdW5nIFVzZXIiLCJpYXQiOjE1MTYyMzkwMjJ9.qH7Zj_m3kY69kxhaQXTa-ivIpytKXXjZc1ZSmapZnGE

輸出將為我們提供解碼後的標頭任何有效載荷:

{"alg":"HS256","typ":"JWT"} {"sub":"1234567890","name":"Baeldung User","iat":1516239022}

如果僅在JWT令牌中定義了標頭和有效載荷部分,那麼我們就可以完成並成功解碼信息。

4.驗證JWT令牌

接下來,我們可以驗證標頭和有效負載的完整性,以確保沒有通過使用簽名部分來更改它們。

4.1 依賴關係

為了進行驗證,我們可以將jjwt添加到我們的pom.xml

<dependency>

 <groupId>io.jsonwebtoken</groupId>

 <artifactId>jjwt</artifactId>

 <version>0.7.0</version>

 </dependency>

我們應該注意,我們需要從版本0.7.0開始的該庫版本。

4.2 配置簽名算法和密鑰規範

要開始驗證有效負載和報頭,我們既需要使用最初用於對令牌進行簽名的簽名算法,也需要密鑰:

SignatureAlgorithm sa = HS256;

 SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getBytes(), sa.getJcaName());

在此示例中,我們已將簽名算法硬編碼為HS256.但是,我們可以解碼標頭的JSON並讀取alg字段以獲取此值。

我們還應該注意,變量secretKey是密鑰的String表示形式。我們可以通過其配置或通過發布JWT的服務公開的REST API將其提供給我們的應用程序。

4.3 執行驗證

現在我們有了簽名算法和密鑰,我們可以開始執行驗證了。讓我們將標頭和有效負載重組到一個未簽名的JWT中,並用“.”將它們連接起來。分隔符:

String tokenWithoutSignature = chunks[0] + "." + chunks[1];

 String signature = chunks[2];

現在我們有了未簽名的令牌和提供的簽名。我們可以使用該庫進行驗證:

DefaultJwtSignatureValidator validator = new DefaultJwtSignatureValidator(sa, secretKeySpec);



 if (!validator.isValid(tokenWithoutSignature, signature)) {

 throw new Exception("Could not verify JWT token integrity!");

 }

讓我們分解一下。

首先,我們使用所選的算法和密碼創建一個驗證器。然後,我們為其提供未簽名的令牌數據和所提供的簽名。

然後。驗證器將生成一個新簽名,並將其與提供的簽名進行比較。如果它們相等,那麼我們已經驗證了報頭和有效載荷的完整性。

5.結論

在本教程中,我們研究了JWT的結構以及如何將其解碼為JSON。
然後,我們使用一個庫來使用其簽名,算法和秘密密鑰來驗證令牌的完整性。