用Java解碼JWT令牌
- java
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。
然後,我們使用一個庫來使用其簽名,算法和秘密密鑰來驗證令牌的完整性。