jwt重放攻击_4个点搞懂JWT、JWS、JWE
1.JWT是何物,有哪些常用的場景
JWT(json web token)是設計一種簡潔,安全,無狀態的token的實現規范rfc7519,通常用于網絡請求方和網絡接收方之間的網絡請求認證。
jwt的常用場景
1.1: restful api接口的無狀態認證, 在傳統的web應用中,我們通常采用session認證。
session認證流程:
客戶端將用戶名/密碼通過某種加密的方式發送給服務器
服務器接收到客戶端請求之后進行驗證,驗證通過后使用Set-Cookie將用戶的唯一sessionid放入到cookie當中,并將生成的sessionid和用戶的關聯信息存入到內存。
客戶端第二次訪問后服務器從當前cookie中取出sessionid并從內存中拿到相同的sessionid. 如果不存在,或者沒有攜帶sessionid則說明該用戶登陸過期,或者未登陸。
session認證的一些缺點:
由于使用session進行認證的方式必須存儲sessionid,當用戶量過大時對服務器內存消耗影響巨大. 如果你沒有設置session的過期時間(關閉瀏覽器并不會導致cookie消失)那么對你的服務器來說消耗是致命的。
如果你沒有將session存在一個所有服務器都可以獲取得到的地方如redis, 那么意味著在本臺服務器上面存儲的sessionid其他服務器無法獲取。用戶進行請求時必須請求到這臺服務器上面。可擴展性較差。
跨平臺性較差,傳統的session認證方式在移動端很難行得通。你必須開發二套不同的邏輯對web和移動端進行認證。
jwt認證流程:
客戶端將用戶名/密碼通過某種加密的方式發送給服務器。
服務器接收到客戶端請求后進行驗證,驗證通過服務器生成token返回給客戶端。客戶端將token存儲在本地。
客戶端每次請求將token攜帶在http header頭中, 服務器端將token取出進行解密。
jwt認證的優點:
服務器端無需保存token,以加解密的方式代替存儲,節省了內存空間。
無狀態的token不依賴于服務器保存會話信息,更利于水平擴展。
相比于傳統的session認證方式,jwt對移動端的支持更友好。
可以看出jwt認證解決了傳統的session認證的一些不足之處。
1.2: 一次性認證:
如需要對某一個應用進行授權使用,此時就可以將jwt進行攜帶訪問。
2.jwt的組成和生成方式
2.1jwt主要由三個部分組成,分別是頭部(header),載荷(payload),簽名(signature)組成。
header:
頭部是用來聲明此jwt的類型和加密算法,它們通常由alg和typ這二個字段組成。
alg字段通常用于表示加密采用的算法。
typ字段通常用于表示類型。
payload:
載荷就是我們存放公共參數/私有參數的地方.通俗點說該字段就是存放系統中用戶的信息和jwt本身的一些信息,rfc文檔本身替我們提供了一組字段的聲明 (Claims)
iss: 該字段表示jwt的簽發者。可以用你的應用唯一標識或者高權限的userid填充此字段。
sub: 該jwt面向的用戶。
aud: jwt的接收方。
exp: jwt的過期時間,通常來說是一個時間戳。
iat: jwt的簽發時間,常來說是一個時間戳。
jti:此jwt的唯一標識。通常用于解決請求中的重放攻擊。該字段在大多數地方沒有被提及或使用。因為使用此字段就意味著必須要在服務器維護一張jti表, 當客戶端攜帶jwt訪問的時候需要在jti表中查找這個唯一標識是否被使用過。使用這種方式防止重放攻擊似乎讓jwt有點怪怪的感覺, 畢竟jwt所宣稱的優點就是無狀態訪問。-.-
{
????"iss":?"appid_xxxxxx"
????"sub":?"012345122",
????"exp":?"1572246721840",
????"iat":?"1592246721840"
}
signature簽名流程:
1.首先將header和payload進行base64編碼,然后使用"."將header和payload拼接起來。類似于像下面這樣:
String?base64data?=?Base64.encode(header)+"."+Base64.encode(payload)2.在將payload和header進行base64之后進行簽名,得到簽名后的數據。簽名所使用的算法來自于header頭中的alg字段。簽名過程類似于像下面這樣:
????final?JWSSigner?signer?=?new?ECDSASigner(this.privateKey);?????????????this.signature?=?signer.sign(base64data);
????????????//第一步,?實例化一個簽名對象
????????????//第二步,對base64data?進行簽名
3.簽名之后將簽名的值和base64之后的header和payload用"."號連接起來。此時一個完整的jwt就出來啦。
jwt的最終結構: header.payload.signature
3.使用jwe來使你的jwt更加安全
簽名到底在干什么:
在上面我們所談到的jwt僅僅是簽名后的jwt。在這里我們需要明白一個概念,那就是簽名并不能保證數據的安全,也就是說如果有人獲取到了你的jwt那么他可以通過轉碼得到你jwt當中所有的信息。那么讀者可能會有點想罵人了,你特么上面說了那么多連一個數據安全都不能保證那么我看那么多有啥作用- -. 別急,我們先來了解一下簽名的概念。其實對于簽名更專業點的來說就是進行了一次哈希散列,對于散列我們首先要保證一下四點概念.
相同的輸入將始終產生相同的輸出。
多個不同的輸入不應產生相同的輸出。
從輸出到輸入應該是不可能的。
給定輸入的任何修改都將導致哈希值發生巨大變化。
從上面4點大家看明白了嗎?哈希與身份驗證結合使用,可以產生強有力的證據來證明給定的消息尚未被修改。也就是說這個jwt從我這里簽發以后無法改變,從而保證了數據來源的可靠性。
當客戶端攜帶jwt進行請求時服務器在執行一遍簽名步驟。如果簽名的值一樣就表示這個jwt是可靠的。此時我們在客戶端和服務器之間就建立一種可信任的token機制。
應該怎樣保證數據安全:
對于如何保證jwt本身的數據安全很多文章或文檔都可以提及,我們可以把上面所生成的jwt成為jws(JSON Web Signed). 他本身的數據并沒有進行加密。
此時如果我們想保證數據的安全就需要使用jwe(JSON Web Encryption)對jwt進行加密。jwe加密的秘文如下所示
// jwe相對于jws來說多了二個組成部分。eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZHQ00ifQ.
?????OKOawDo13gRp2ojaHV7LFpZcgV7T6DVZKTyKOMTYUmKoTCVJRgckCL9kiMT03JGe
?????ipsEdY3mx_etLbbWSrFr05kLzcSr4qKAq7YN7e9jwQRb23nfa6c9d-StnImGyFDb
?????Sv04uVuxIp5Zms1gNxKKK2Da14B8S4rzVRltdYwam_lDp5XnZAYpQdb76FdIKLaV
?????mqgfwX7XWRxv2322i-vDxRfqNzo_tETKzpVLzfiwQyeyPGLBIO56YJ7eObdv0je8
?????1860ppamavo35UgoRdbYaBcoh9QcfylQr66oc6vFWXRcZ_ZT2LawVCWTIy3brGPi
?????6UklfCpIMfIjf7iGdXKHzg.
?????48V1_ALb6US04U3b.
?????5eym8TW_c8SuK0ltJ3rpYIzOeDQz7TALvtu6UG9oMo4vpzs9tX_EFShS8iB7j6ji
?????SdiwkIr3ajwQzaBtQD_A.
?????XFBoMYUZodetZdvTiFvSkQ
jwe的5個組成部分:
JWE header: 描述用于創建jwe加密密鑰和jwe密文的加密操作,類似于jws中的header。參數不一一描述,詳情請見jwe header參數
JWE Encrypted Key:用來加密文本內容所采用的算法。
JWE initialization vector: 加密明文時使用的初始化向量值,有些加密方式需要額外的或者隨機的數據。這個參數是可選的。
JWE Ciphertext:明文加密后產生的密文值。
JWE Authentication Tag:數字認證標簽。
??{
??????"protected":"jwe受保護的header頭",
??????"unprotected":"JWE?Shared?Unprotected?Header數據",
??????"header":"",
??????"encrypted_key":"密鑰加密后數據????",
??????"aad":"額外的認證數據",
??????"iv":"同上的?JWE?initialization?vector",
??????"ciphertext":"同上的JWE?Ciphertext",
??????"tag":"同上的JWE?Authentication?Tag"
?????}
jwe創建流程:
根據頭部 alg 的聲明,將header頭進行編碼
隨機生成密鑰
加密密鑰
生成iv如果不需要,此步驟可以省略.
加密原始報文
生成認證算法得到Authentication Tag.
如果明文有聲明zip壓縮,那么壓縮明文
4. jwt的缺點以及常見的理解誤區
缺點:
無法主動的過期token. 常見的場景為后臺踢出用戶或封禁用戶,此時若是token還在生效
時間范圍內,那么意味著該用戶在被踢出系統后還可以在這個時間范圍內進行訪問。又或者用戶修改了密碼,此時原token依然可以進行加解密也就代表著用戶仍然可以繼續訪問。更為致命的是大多數客戶端會將token存放在Local Storage或者vuex中,這意味著除非用戶點擊退出登陸。否則就算關閉軟件在重新打開也會造成原密碼可以登陸的假象。jwt對比于傳統的session認證方案并不會提高運行效率,因為本質上jwt做的是一個以時間換空間的動作。頻繁的加解密會帶來不小的性能開銷。
常見的理解誤區:
對jwt進行存儲,這個是最常見的理解誤區。事實上很多人都覺得將jwt進行存儲可以完美的解決主動過期的問題, 然而這是一種賠了夫人又損兵的做法。既無法節省空間也無法節省時間。如果你的應用必須要主動過期的功能,那么我推薦你使用傳統的session,事實上傳統的session也有不少成熟的解決方案。如spring-session等。
jwt被盜用會導致數據泄漏不安全, 事實上使用jwe加密的jwt是不存在數據不安全的問題的。第二,jwt的數據一般都是非敏感數據,由于簽名機制的存在所以你盜用了jwt做不了任何事情。
不存儲如何實現退出功能。直接在客戶端清除token就行了。因為服務器不存儲所以只需要在客戶端清除token就可以做到用戶退出。
將token的時期設計的非常長。這是一個會造成很多隱性問題的設計,比如上述的密碼修改等問題。這個時候可以參見oauth2的做法,將token的過期時間設置為一小時,但是增加一個refreshToken。客戶端在沒有觸發退出或者修改密碼等操作時通過refreshToken來刷新token。
?你在看嗎?
總結
以上是生活随笔為你收集整理的jwt重放攻击_4个点搞懂JWT、JWS、JWE的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 学习笔记_jquery(js)遍历页面标
- 下一篇: discuz安装_手动搭建 Discuz