Java生成及校驗token的實踐
What is token?
token是令牌的意思,作用就像“通關令牌”一樣,持有token的請求會被“放行”,不持有token的請求可以被攔截(可以設置白名單使不被攔截,例如登陸請求)。
token是由服務端創(chuàng)建的一串字符串,登陸成功后發(fā)送給前端存儲在瀏覽器或本地中,以后每次發(fā)送請求都攜帶上。
1. 使用攔截器在請求發(fā)出前在請求頭中添加上 token。
2. 將 token 存儲在瀏覽器的 cookies 中,符合一些條件每次請求都會自動帶上 token。
Token安全問題
- 在存儲的時候把token進行對稱加密存儲,用時解開。
- 將請求URL、時間戳、token三者進行合并加鹽簽名,服務端校驗有效性。
- 這兩種辦法的出發(fā)點都是:竊取你存儲的數(shù)據(jù)較為容易,而反匯編你的程序hack你的加密解密和簽名算法是比較難的。然而其實說難也不難,所以終究是防君子不防小人的做法。話說加密存儲一個你要是被人扒開客戶端看也不會被噴明文存儲……
- 方法1它拿到存儲的密文解不開、方法2它不知道你的簽名算法和鹽,兩者可以結合食用。
- 但是如果token被人拷走,他自然也能植入到自己的手機里面,那到時候他的手機也可以以你的身份來用著,這你就瞎了。
- 于是可以提供一個讓用戶可以主動expire一個過去的token類似的機制,在被盜的時候能遠程止損。
- 在網絡層面上token明文傳輸?shù)脑挄浅5奈kU,所以建議一定要使用HTTPS,并且把token放在post body里
Why do we use token?
在前后端分離的web項目中,HTTP是無狀態(tài)協(xié)議,即使使用賬號密碼登陸,后端仍然無法分辨是誰發(fā)出的請求,要么后端不需要確認請求者的身份,要么每次請求都攜帶身份信息供后端確認。
顯然第一種方法對軟件的安全會造成極大的威脅,那么第二種方法就被改善成了token,token就是加密了的用戶身份信息。
token組成(Composition of token)
以jwt(java web token)為例,下圖介紹了詳細介紹了token的組成。
校驗token(Verify token)
這里只說最基礎的校驗。
token的加密一般是可逆的,后端接收到token中,還可以根據(jù)加密的算法再進行解密,以獲取荷載中的用戶信息,因此荷載中不能放置密碼等信息。
第三部分由于加入了自己制定的秘鑰(秘鑰一般保存在后端代碼中),解密成功后會與前兩部分和保存的秘鑰進行對比,對比成功了才算token驗證通過。經過這樣的雙重保障,這三部分每一部分被篡改都會被發(fā)現(xiàn)。
校驗流程:
實操:
生成token(Generate token)
以生成jwt為例子,代碼如下:
<!-- 引入jwt --> <dependency> <groupId>com.auth0</groupId> <artifactId>java-jwt</artifactId> <version>3.8.2</version> </dependency>
校驗token(Verificationtoken)
@Slf4j public class JwtUtil { /** * 使用固定的解密秘鑰 */ private static final String SECRET = TOKEN_SECRET; /** * @version: V1.0 * @description: 生成token并驗證token并解密token中的信息 * @param: userInfo 用戶手機號和用戶Id * @return: java.lang.String 返回token **/ public static String getToken(UserInfoEntity userInfo) { try{ //用秘鑰生成簽名 Algorithm algorithm = Algorithm.HMAC256(SECRET); //默認頭部+載荷(手機號/id)+簽名=jwt String jwtToken= JWT.create() .withClaim("userPhone", userInfo.getUserPhone()) .withClaim("userId", userInfo.getUserId()) .sign(algorithm); log.info("用戶{}的token生成成功:{}",userInfo.getUserId(),jwtToken); return jwtToken; }catch (Exception e){ log.error("用戶{}的token生成異常:{}",userInfo.getUserId(),e); return null; } } /** * @version: V1.0 * @description: 校驗token是否正確 * @param: token * @param: userPhone * @return: UserInfoEntity token中的用戶信息(姓名/id) **/ public static UserInfoEntity verify(String token) { try { // 根據(jù)用戶信息userInfo生成JWT效驗器 Algorithm algorithm = Algorithm.HMAC256(SECRET); JWTVerifier verifier = JWT.require(algorithm) .build(); // 效驗TOKEN verifier.verify(token); log.info("token:{}校驗成功成功",token); //返回token內容 return getTokenInfo(token); } catch (Exception exception) { log.error("token校驗異常:{}",exception); return null; } } /** * @version: V1.0 * @Title: getUsername * @description: 從Token中解密獲得Token中的用戶信息 * @param: token * @return: UserInfoEntity token中的用戶信息(姓名/id) **/ private static UserInfoEntity getTokenInfo(String token) { try { DecodedJWT jwt = JWT.decode(token); UserInfoEntity userInfo=new UserInfoEntity(); userInfo.setUserPhone(jwt.getClaim("userPhone").asString()); userInfo.setUserId(jwt.getClaim("userId").asString()); log.info("用戶{}從token獲取用戶信息成功",userInfo.getUserId()); return userInfo; } catch (JWTDecodeException e) { log.error("從token:{}獲取用戶信息異常:{}",token,e); return null; } } }
總結:
在實際應用中,還應考慮安全性措施,如使用安全的隨機數(shù)生成器生成密鑰、定期更換密鑰、使用 HTTPS 等。
Token 的生成和校驗機制為應用程序提供了一種安全的身份驗證和授權方式,可以用于用戶認證、API 訪問控制等場景。正確實現(xiàn)和使用 Token 機制可以提高應用程序的安全性和用戶體驗。
到此這篇關于Java生成及校驗token的實踐的文章就介紹到這了,更多相關Java生成及校驗token內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Spring?MVC?請求映射路徑的配置實現(xiàn)前后端交互
在Spring?MVC中,請求映射路徑是指與特定的請求處理方法關聯(lián)的URL路徑,這篇文章主要介紹了Spring?MVC?請求映射路徑的配置,實現(xiàn)前后端交互,需要的朋友可以參考下2023-09-09Spring Boot訪問靜態(tài)資源css/js,你真的懂了嗎
在搭建springboot時經常需要在html中訪問一些靜態(tài)資源,很多朋友不清楚如何在 Spring Boot中訪問靜態(tài)資源,本文給大家?guī)韮煞N解決方案,感興趣的朋友跟隨小編一起看看吧2021-05-05