本文目錄一覽:
java jwt token 生成很慢啊
jwt不算慢,基本是毫秒,你測試的方法估計有問題,單元測試1次jwt生成基本都是1~2秒,因為java程序剛剛啟動佔用大量資源,你循環1000次jwt生成速度對比就知道了, 基本是毫秒級別!
如何在Java 中創建和驗證JWT
用戶發起登錄請求,服務端創建一個加密後的jwt信息,作為token返回值,在後續請求中jwt信息作為請求頭,服務端正確解密後可獲取到存儲的用戶信息,表示驗證通過;解密失敗說明token無效或者已過期。
加密後jwt信息如下所示,是由.分割的三部分組成,分別為Header、Payload、Signature。
eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiJqd3QiLCJpYXQiOjE0NzEyNzYyNTEsInN1YiI6IntcInVzZXJJZFwiOjEsXCJyb2xlSWRcIjoxfSIsImV4cCI6MTQ3MTMxOTQ1MX0.vW-pPSl5bU4dmORMa7UzPjBR0F6sqg3n3hQuKY8j35o
Header包含兩部分信息,alg指加密類型,可選值為HS256、RSA等等,typ=JWT為固定值,表示token的類型。
{
“alg”: “HS256”,
“typ”: “JWT”
}
Payload是指簽名信息以及內容,一般包括iss (發行者), exp (過期時間), sub(用戶信息), aud (接收者),以及其他信息,詳細介紹請參考官網。
{
“sub”: “1234567890”,
“name”: “John Doe”,
“admin”: true
}
Signature則為對Header、Payload的簽名。
HMACSHA256( base64UrlEncode(header) + “.” + base64UrlEncode(payload), secret)
在jwt官網,可以看到有不同語言的實現版本,這裡使用的是Java版的jjwt。話不多說,直接看代碼,加解密都很簡單:
/**
* 創建 jwt
* @param id
* @param subject
* @param ttlMillis
* @return
* @throws Exception
*/
public String createJWT(String id, String subject, long ttlMillis) throws Exception {
SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256 ;
long nowMillis = System. currentTimeMillis();
Date now = new Date( nowMillis);
SecretKey key = generalKey();
JwtBuilder builder = Jwts. builder()
.setId(id)
.setIssuedAt(now)
.setSubject(subject)
.signWith(signatureAlgorithm, key);
if (ttlMillis = 0){
long expMillis = nowMillis + ttlMillis;
Date exp = new Date( expMillis);
builder.setExpiration( exp);
}
return builder.compact();
}
/**
* 解密 jwt
* @param jwt
* @return
* @throws Exception
*/
public Claims parseJWT(String jwt) throws Exception{
SecretKey key = generalKey();
Claims claims = Jwts. parser()
.setSigningKey( key)
.parseClaimsJws( jwt).getBody();
return claims;
}
加解密的key是通過固定字元串轉換而生成的;subject為用戶信息的json字元串;ttlMillis是指token的有效期,時間較短,需要定時更新。
這裡要介紹的token刷新方式,是在生成token的同時生成一個有效期較長的refreshToken,後續由客戶端定時根據refreshToken來獲取最新的token。瀏覽器與服務端之間建立sse(server send event)請求,來實現刷新。關於sse在前面博文中有介紹過,此處略過不提。
來,科普一下JWT
1. JSON Web Token是什麼
JSON Web Token (JWT)是一個開放標準(RFC 7519),它定義了一種緊湊的、自包含的方式,用於作為JSON對象在各方之間安全地傳輸信息。該信息可以被驗證和信任,因為它是數字簽名的。
2. 什麼時候你應該用JSON Web Tokens
下列場景中使用JSON Web Token是很有用的:
Authorization (授權) : 這是使用JWT的最常見場景。一旦用戶登錄,後續每個請求都將包含JWT,允許用戶訪問該令牌允許的路由、服務和資源。單點登錄是現在廣泛使用的JWT的一個特性,因為它的開銷很小,並且可以輕鬆地跨域使用。
Information Exchange (信息交換) : 對於安全的在各方之間傳輸信息而言,JSON Web Tokens無疑是一種很好的方式。因為JWTs可以被簽名,例如,用公鑰/私鑰對,你可以確定發送人就是它們所說的那個人。另外,由於簽名是使用頭和有效負載計算的,您還可以驗證內容沒有被篡改。
3. JSON Web Token的結構是什麼樣的
JSON Web Token由三部分組成,它們之間用圓點(.)連接。這三部分分別是:
因此,一個典型的JWT看起來是這個樣子的:
接下來,具體看一下每一部分:
Header
header典型的由兩部分組成:token的類型(「JWT」)和演算法名稱(比如:HMAC SHA256或者RSA等等)。
例如:
然後,用Base64對這個JSON編碼就得到JWT的第一部分
Payload
Public claims : 可以隨意定義。
下面是一個例子:
對payload進行Base64編碼就得到JWT的第二部分
Signature
為了得到簽名部分,你必須有編碼過的header、編碼過的payload、一個秘鑰,簽名演算法是header中指定的那個,然對它們簽名即可。
例如:
簽名是用於驗證消息在傳遞過程中有沒有被更改,並且,對於使用私鑰簽名的token,它還可以驗證JWT的發送方是否為它所稱的發送方。
看一張官網的圖就明白了:
4. JSON Web Tokens是如何工作的
在認證的時候,當用戶用他們的憑證成功登錄以後,一個JSON Web Token將會被返回。此後,token就是用戶憑證了,你必須非常小心以防止出現安全問題。一般而言,你保存令牌的時候不應該超過你所需要它的時間。
無論何時用戶想要訪問受保護的路由或者資源的時候,用戶代理(通常是瀏覽器)都應該帶上JWT,典型的,通常放在Authorization header中,用Bearer schema。
header應該看起來是這樣的:
伺服器上的受保護的路由將會檢查Authorization header中的JWT是否有效,如果有效,則用戶可以訪問受保護的資源。如果JWT包含足夠多的必需的數據,那麼就可以減少對某些操作的資料庫查詢的需要,儘管可能並不總是如此。
如果token是在授權頭(Authorization header)中發送的,那麼跨源資源共享(CORS)將不會成為問題,因為它不使用cookie。
下面這張圖顯示了如何獲取JWT以及使用它來訪問APIs或者資源:
5. 基於Token的身份認證 與 基於伺服器的身份認證
5.1. 基於伺服器的身份認證
在討論基於Token的身份認證是如何工作的以及它的好處之前,我們先來看一下以前我們是怎麼做的:
HTTP協議是無狀態的,也就是說,如果我們已經認證了一個用戶,那麼他下一次請求的時候,伺服器不知道我是誰,我們必須再次認證
傳統的做法是將已經認證過的用戶信息存儲在伺服器上,比如Session。用戶下次請求的時候帶著Session ID,然後伺服器以此檢查用戶是否認證過。
這種基於伺服器的身份認證方式存在一些問題:
Sessions : 每次用戶認證通過以後,伺服器需要創建一條記錄保存用戶信息,通常是在內存中,隨著認證通過的用戶越來越多,伺服器的在這裡的開銷就會越來越大。
Scalability : 由於Session是在內存中的,這就帶來一些擴展性的問題。
CORS : 當我們想要擴展我們的應用,讓我們的數據被多個移動設備使用時,我們必須考慮跨資源共享問題。當使用AJAX調用從另一個域名下獲取資源時,我們可能會遇到禁止請求的問題。
CSRF : 用戶很容易受到CSRF攻擊。
5.2. JWT與Session的差異
相同點是,它們都是存儲用戶信息;然而,Session是在伺服器端的,而JWT是在客戶端的。
Session方式存儲用戶信息的最大問題在於要佔用大量伺服器內存,增加伺服器的開銷。
而JWT方式將用戶狀態分散到了客戶端中,可以明顯減輕服務端的內存壓力。
Session的狀態是存儲在伺服器端,客戶端只有session id;而Token的狀態是存儲在客戶端。
5.3. 基於Token的身份認證是如何工作的
基於Token的身份認證是無狀態的,伺服器或者Session中不會存儲任何用戶信息。
雖然這一實現可能會有所不同,但其主要流程如下:
注意:
5.4. 用Token的好處
無狀態和可擴展性: Tokens存儲在客戶端。完全無狀態,可擴展。我們的負載均衡器可以將用戶傳遞到任意伺服器,因為在任何地方都沒有狀態或會話信息。
安全: Token不是Cookie。(The token, not a cookie.)每次請求的時候Token都會被發送。而且,由於沒有Cookie被發送,還有助於防止CSRF攻擊。即使在你的實現中將token存儲到客戶端的Cookie中,這個Cookie也只是一種存儲機制,而非身份認證機制。沒有基於會話的信息可以操作,因為我們沒有會話!
還有一點,token在一段時間以後會過期,這個時候用戶需要重新登錄。這有助於我們保持安全。還有一個概念叫token撤銷,它允許我們根據相同的授權許可使特定的token甚至一組token無效。
5.5. JWT與OAuth的區別
寫在最後:我為大家準備了一些適合於1-5年以上開發經驗的java程序員面試涉及到的絕大部分面試題及答案做成了文檔和學習筆記文件以及架構視頻資料免費分享給大家(包括Dubbo、Redis、Netty、zookeeper、Spring cloud、分散式、高並發等架構技術資料),希望可以幫助到大家。
java jwt如何刷新過期時間
客戶端
auth_header = JWT.encode({ user_id: 123, iat: Time.now.to_i, # 指定token發布時間 exp: Time.now.to_i + 2 # 指定token過期時間為2秒後,2秒時間足夠一次HTTP請求,同時在一定程度確保上一次token過期,減少replay attack的概率;}, “my shared secret”)
RestClient.get(“”, authorization: auth_header)
服務端
class ApiController ActionController::Base
attr_reader :current_user
before_action :set_current_user_from_jwt_token
def set_current_user_from_jwt_token
# Step 1:解碼JWT,並獲取User ID,這個時候不對Token簽名進行檢查
# the signature. Note JWT tokens are *not* encrypted, but signed.
payload = JWT.decode(request.authorization, nil, false) # Step 2: 檢查該用戶是否存在於資料庫
@current_user = User.find(payload[‘user_id’])
# Step 3: 檢查Token簽名是否正確.
JWT.decode(request.authorization, current_user.api_secret)
# Step 4: 檢查 “iat” 和”exp” 以確保這個Token是在2秒內創建的.
now = Time.now.to_i if payload[‘iat’] now || payload[‘exp’] now # 如果過期則返回401
end
rescue JWT::DecodeError
# 返回 401
endend
原創文章,作者:KLWC,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/133667.html