您好,登錄后才能下訂單哦!
本文小編為大家詳細介紹“Spring Boot怎么集成JWT實現前后端認證”,內容詳細,步驟清晰,細節處理妥當,希望這篇“Spring Boot怎么集成JWT實現前后端認證”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學習新知識吧。
JWT(全稱:Json Web Token)是一個開放標準(RFC 7519),它定義了一種緊湊的、自包含的方式,用于作為JSON對象在各方之間安全地傳輸信息。
每個用戶的登錄信息都會保存到服務器的Session中,隨著用戶的增多,服務器開銷會明顯增大。
Session的信息存放在服務器的內存中,對于分布式應用會導致失效,雖然可以將session的信息統一存放在Redis的緩存中,但這樣可能增加了復雜性。
由于Session認證是基于Cookie實現,而針對于非瀏覽器端和手機的移動端都不適用。
前后端分離系統,由于前后端存在跨域,而Cookie信息無法跨越,所以采用Session認證也是無法繼續寧跨域認證。
簡潔:JWT Token數據量小,傳輸速度也很快。
跨語言: JWT Token是以JSON加密形式保存在客戶端的,所以JWT是跨語言的,任何web形式都支持。 跨平臺:不依賴于cookie和session,無需將session信息存放在服務端,非常適合于分布式應用,應用于擴展。
JWT第一部分是頭部分,它是一個描述JWT元數據的Json對象,通常如下所示。
{ "alg": "HS256", "typ": "JWT" }
alg屬性表示簽名使用的算法,默認為HMAC SHA256(寫為HS256),typ屬性表示令牌的類型,JWT令牌統一寫為JWT。
JWT第二部分是Payload,也是一個Json對象,除了包含需要傳遞的數據,還有七個默認的字段供選擇。 iss:發行人 exp:到期時間 sub:主題 aud:用戶 nbf:在此之前不可用 iat:發布時間 jti:JWT ID用于標識該JWT
{ //默認字段 "sub":"主題123", //自定義字段 "name":"java", "isAdmin":"true", "loginTime":"2021-12-05 12:00:03" }
需要注意的是,默認情況下JWT是未加密的,任何人都可以解讀其內容,因此如果一些敏感信息不要存放在此,以防信息泄露。JSON對象也使用Base64 URL算法轉換為字符串保存。
簽名哈希部分是對上面兩部分數據簽名,需要使用base64編碼后的header和payload數據,通過指定的算法生成哈希,以確保數據不會被篡改。
<dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.9.1</version> </dependency>
public class JwtUtil { //創建jwt public static String createJWT(String subject, String issue, Object claim, long ttlMillis) { //當前時間 long nowMillis = System.currentTimeMillis(); //過期時間 long expireMillis = nowMillis + ttlMillis; String result = Jwts.builder() .setSubject(subject) //設置主題 .setIssuer(issue) //發行者 .setId(issue)//jwtID .setExpiration(new Date(expireMillis)) //設置過期日期 .claim("user", claim)//主題,可以包含用戶信息 .signWith(getSignatureAlgorithm(), getSignedKey())//加密算法 .compressWith(CompressionCodecs.DEFLATE).compact();//對載荷進行壓縮 return result; } // 解析jwt public static Jws<Claims> pareseJWT(String jwt) { Jws<Claims> claims; try { claims = Jwts.parser().setSigningKey(getSignedKey()) .parseClaimsJws(jwt); } catch (Exception ex) { claims = null; } return claims; } //獲取主題信息 public static Claims getClaims(String jwt) { Claims claims; try { claims = Jwts.parser().setSigningKey(getSignedKey()) .parseClaimsJws(jwt).getBody(); } catch (Exception ex) { claims = null; } return claims; } } /** * 獲取密鑰 * * @return Key */ private static Key getSignedKey() { byte[] apiKeySecretBytes = DatatypeConverter .parseBase64Binary(getAuthKey()); Key signingKey = new SecretKeySpec(apiKeySecretBytes, getSignatureAlgorithm().getJcaName()); return signingKey; } private static SignatureAlgorithm getSignatureAlgorithm() { return SignatureAlgorithm.HS256; } //獲取密鑰,可以動態配置 public static String getAuthKey() { String auth = "123@#1234"; }
Component public class TokenInterceptor extends HandlerInterceptorAdapter { public static Log logger = LogManager.getLogger(TokenInterceptor.class); @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String uri = request.getRequestURI(); logger.info("start TokenInterceptor preHandle.." + uri); //需要過濾特殊請求 if (SystemUtil.isFree(uri) || SystemUtil.isProtected(uri)) { return true; } String metohd=request.getMethod().toString(); logger.info("TokenInterceptor request method:"+metohd); //options 方法需要過濾 if("OPTIONS".equals(metohd)) { return true; } //是否開啟token認證 boolean flag = SystemUtil.getVerifyToken(); ResponseResult result = new ResponseResult(); //從請求的head信息中獲取token String token = request.getHeader("X-Token"); if (flag) { if(StringUtils.isEmpty(token)) { token=request.getParameter("X-Token"); } // token不存在 if (StringUtils.isEmpty(token)) { result.setCode(ResultCode.NEED_AUTH.getCode()); result.setMsg(ResultCode.NEED_AUTH.getMsg()); WebUtil.writeJson(result, response); return false; } else { Claims claims = JwtUtil.getClaims(token); String subject = ""; if (claims != null) { subject = claims.getSubject(); // 驗證主題 if (StringUtils.isEmpty(subject)) { result.setCode(ResultCode.INVALID_TOKEN.getCode()); result.setMsg(ResultCode.INVALID_TOKEN.getMsg()); WebUtil.writeJson(result, response); return false; } } else { result.setCode(ResultCode.INVALID_TOKEN.getCode()); result.setMsg(ResultCode.INVALID_TOKEN.getMsg()); WebUtil.writeJson(result, response); return false; } } } return true; } }
@Configuration public class WebConfig implements WebMvcConfigurer { @Resource private TokenInterceptor tokenInterceptor; public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(tokenInterceptor).addPathPatterns("/**"); } }
@RequestMapping("login") public Result login(HttpServletResponse response) { Map<String, Object> map = new HashMap<>(); // Result result = loginAuth(user); int code = result.getCode(); //登錄認證成功 if (code ==ResultCode.SUCCESS) { //默認為7天 Long ttlMillis = 7*1000 * 60 * 60 * 24; //過期時間 long expreTime = System.currentTimeMillis() + ttlMillis; String tokenKey = UUID.randomUUID().toString(); String tokenId = JwtUtil.createJWT(user.getUserId(), tokenKey, user.getPassword(), expreTime); map.put("expreTime", expreTime); map.put("tokenId", tokenId); } else { logger.error("login error:" +FastJsonUtil.toJSONString(result)); } return result; }
讀到這里,這篇“Spring Boot怎么集成JWT實現前后端認證”文章已經介紹完畢,想要掌握這篇文章的知識點還需要大家自己動手實踐使用過才能領會,如果想了解更多相關內容的文章,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。