網(wǎng)站首頁 編程語言 正文
問題描述
使用io.jsonwebtoken.Jwts構造了一個token,在解析這個token時,發(fā)現(xiàn)解析秘鑰和構建秘鑰不完全相同也可以成功解析,代碼如下
簽發(fā)token
/** 測試生成token */
@Test
public void testJwt() {
JwtBuilder jwtBuilder = Jwts.builder()
// 唯一ID {"":""}
.setId("888")
// 接受的用戶 {"sub":"Rose"}
.setSubject("Rose")
// 簽發(fā)時間 {"iat":"。。。"}
.setIssuedAt(new Date())
// 簽名算法 及秘鑰
.signWith(SignatureAlgorithm.HS256, "xxxx");
// 簽發(fā)token
String token = jwtBuilder.compact();
System.out.println(token);
String[] split = token.split("\\.");
// 頭部
System.out.println(Base64Codec.BASE64.decodeToString(split[0]));
// 載荷
System.out.println(Base64Codec.BASE64.decodeToString(split[1]));
// 算法及秘鑰 這個會亂碼
System.out.println(Base64Codec.BASE64.decodeToString(split[2]));
}
解析token
/** 解析token */
@Test
public void testParseToken() {
String token = "eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiI4ODgiLCJzdWIiOiJSb3NlIiwiaWF0IjoxNjMyNzMxMzYyfQ.9GZJUoTNwJuMh5tFMd3giJh36YNuCnFuWsDKONOg2C8";
// 得到的是荷載
Claims claims = (Claims) Jwts.parser()
// 解析時的秘鑰一定要和簽發(fā)時秘鑰相同,但是發(fā)現(xiàn)這了的秘鑰為4-7個x都是可以成功解析的
.setSigningKey("xxxx")
// .parse(token)
.parseClaimsJws(token)
.getBody();
System.out.println(claims);
}
在簽發(fā)時我的秘鑰是四個x,但是在解析時,4-7個x都能成功解析,我很不理解,雖然不是什么秘鑰都可以成功解析,但是近似的就能解析也太不安全了吧
問題分析
我第一時間想到的是去網(wǎng)上查,沒有想到第一時間自己看源碼,因為可能源碼一時半會看不出來個啥。去網(wǎng)上查了一下,果然查到了一些有用的東西,然后我點進源碼看了一下,一下子就清楚了。
先查看設置秘鑰的地方,io.jsonwebtoken.JwtBuilder有一個默認的實現(xiàn)類io.jsonwebtoken.impl.DefaultJwtBuilder,我們看看他的signWith方法,signWith有三個重載形式,我們只看我們調用的那個就行了
關鍵的地方我標出來了,signWith拿到秘鑰之后是先將秘鑰用base64解碼之后再進行操作的。
然后再看解析token時的地方,io.jsonwebtoken.JwtParser也有一個默認的實現(xiàn)類io.jsonwebtoken.impl.DefaultJwtParser,設置秘鑰的方法setSigningKey也有三個重載形式,我們使用的是下面這個
可以看到,setSigningKey方法也將拿到的秘鑰用base64解碼了,咋一看好像沒什么問題,解碼就解碼唄,反正兩邊都解了,同一個字符串,解碼過肯定是一樣的結果,但問題恰巧就出現(xiàn)在這里。
雖然相同的字符串經(jīng)過base64解碼過后也一定是相同的,但是不同的字符串經(jīng)過base64解碼過后也可能是相同的!!
下面是我的測試
可以看到,我測試了三種不同地方的工具類,在將xxxx和xxxxx按照base64解碼時,都解碼成相同的byte數(shù)組了。在jwt設置秘鑰和解析秘鑰時,使用的是第一種,所以就不難理解,為啥秘鑰即便不完全相同,只要近似也能解析。
解決問題
雖然搞清楚了原理,那怎么解決這個問題呢?或者這是jjwt的一個或base64的bug?是不是base64的bug我不知道,但是一定不是jjwt的bug,只是我們調用api是沒有按照人家要求調用。再來看看構建token時設置秘鑰的方法
人家方法的變量名叫:base64EncodedSecretKey,就是想讓你傳一個經(jīng)過base64編碼過后的字符串。接口上也有明確的注釋:
在解析token時設置秘鑰的方法也有同樣的注釋。如果按照api要求來調用,就沒有問題了,因為base64是對稱加密的,解碼被加密過后一樣的字符串,得到的肯定是兩個一樣原始內(nèi)容。
反思總結
在調用api時,沒有好好的看別人的文檔或是注釋,記大過一次。
聯(lián)想拓展
我對base64了解沒那么深,只知道是一個對稱加密的算法,但是也會感到奇怪,為什么對不同的字符串進行解碼時,能得到相同的結果呢?
我只能嘗試這么理解:Base64在加密時,是通過一步一步加密的,相同的東西,在加密時經(jīng)過的步驟都是相同的,所以最終加密出來也是相同的。但是解密則有點不同,什么不同呢?如果你是經(jīng)過我Base64加密過后,你再來經(jīng)過我解密,我能按照加密過程的逆過程,一步一步把你還原成原來的樣子。但是如果你壓根就沒有經(jīng)過我Base64加密,你卻要來走我Base64的還原過程,那我在還原的過程中,有的步驟都沒法走,直接跳過了,最后把你“還原”。所以那些近似的、不是經(jīng)過Base64加密的字符串,在經(jīng)過Base64解密時,都有一些相同步驟跳過了,所以最終解密過后得到了相同的東西。當然,這都是我自己的理解。
另外,在測試過程中,我發(fā)現(xiàn),有的地方的Base64工具類,測試的結果不一樣,上面測試了三個base64解碼,分別是:
- io.jsonwebtoken.impl.TextCodec.BASE64
- io.jsonwebtoken.impl.Base64Codec
- cn.hutool.core.codec.Base64
三者在解密五個x時,結果都是一樣的,也都和4個x的解密相同。但是在解密6個x和7個x時,就有所不同了
前兩者解密6個x和7個x時,得到的結果依然和4個x是相同的,但是第三者解密出來是不同的,不知道這是為啥。
原文鏈接:https://blog.csdn.net/ql_7256/article/details/120522555
相關推薦
- 2022-01-17 git git版本回退 回滾 解決方案
- 2022-01-02 無法將“node.exe”項識別為 cmdlet、函數(shù)、腳本文件或可運行程序的名稱
- 2022-11-10 Netcore?Webapi返回數(shù)據(jù)的三種方式示例_C#教程
- 2022-07-07 Linux?shell進行文件解壓,復制和移動詳解_linux shell
- 2022-10-07 k8s中如何實現(xiàn)pod自動擴縮容詳解_云其它
- 2023-01-08 利用Qt實現(xiàn)獲取計算機的硬件信息_C 語言
- 2022-10-19 Python基礎之類的定義和使用詳解_python
- 2022-12-24 Python中requirements.txt簡介(推薦)_python
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細win安裝深度學習環(huán)境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結構-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支