JWT相關整合
阿新 • • 發佈:2021-01-10
JWT類:
package com.ujs.edu.medicine.JWT; import io.jsonwebtoken.Claims; import io.jsonwebtoken.JwtBuilder; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; import java.util.Date; import java.util.HashMap; import java.util.Map; import java.util.UUID; import com.ujs.edu.medicine.dataobject.YunjiayiUser; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; import org.apache.tomcat.util.codec.binary.Base64; /** * @Author:jimisun * @Description: * @Date:Created in 14:08 2018/8/15 * @Modified By: */ public class JwtUtil { /** * 使用者登入成功後生成Jwt * 使用Hs256演算法 私匙使用使用者密碼 * * @param ttlMillis jwt過期時間 * @param user 登入成功的user物件 * @return */ public static String createJWT(long ttlMillis, YunjiayiUser user) { //指定簽名的時候使用的簽名演算法,也就是header那部分,jjwt已經將這部分內容封裝好了。 SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256; //生成JWT的時間 long nowMillis = System.currentTimeMillis(); Date now = new Date(nowMillis); //建立payload的私有宣告(根據特定的業務需要新增,如果要拿這個做驗證,一般是需要和jwt的接收方提前溝通好驗證方式的) Map<String, Object> claims = new HashMap<String, Object>(); claims.put("id", user. getUser_Id()); claims.put("username", user.getUsername()); claims.put("password", user.getPassword()); //生成簽名的時候使用的祕鑰secret,這個方法本地封裝了的,一般可以從本地配置檔案中讀取,切記這個祕鑰不能外露哦。它就是你服務端的私鑰,在任何場景都不應該流露出去。一旦客戶端得知這個secret, 那就意味著客戶端是可以自我簽發jwt了。 SecretKey key = generalKey(); //生成簽發人 String subject = user.getUsername(); //下面就是在為payload新增各種標準宣告和私有聲明瞭 //這裡其實就是new一個JwtBuilder,設定jwt的body JwtBuilder builder = Jwts.builder() //如果有私有宣告,一定要先設定這個自己建立的私有的宣告,這個是給builder的claim賦值,一旦寫在標準的宣告賦值之後,就是覆蓋了那些標準的宣告的 .setClaims(claims) //設定jti(JWT ID):是JWT的唯一標識,根據業務需要,這個可以設定為一個不重複的值,主要用來作為一次性token,從而回避重放攻擊。 .setId(UUID.randomUUID().toString()) //iat: jwt的簽發時間 .setIssuedAt(now) //代表這個JWT的主體,即它的所有人,這個是一個json格式的字串,可以存放什麼userid,roldid之類的,作為什麼使用者的唯一標誌。 .setSubject(subject) //設定簽名使用的簽名演算法和簽名使用的祕鑰 .signWith(signatureAlgorithm, key); if (ttlMillis >= 0) { long expMillis = nowMillis + ttlMillis; Date exp = new Date(expMillis); //設定過期時間 builder.setExpiration(exp); } return builder.compact(); } /** * Token的解密 * @param token 加密後的token * @param user 使用者的物件 * @return */ public static Claims parseJWT(String token, YunjiayiUser user) { //簽名祕鑰,和生成的簽名的祕鑰一模一樣 SecretKey key = generalKey(); //得到DefaultJwtParser Claims claims = Jwts.parser() //設定簽名的祕鑰 .setSigningKey(key) //設定需要解析的jwt .parseClaimsJws(token).getBody(); return claims; } /** * 校驗token * 在這裡可以使用官方的校驗,我這裡校驗的是token中攜帶的密碼於資料庫一致的話就校驗通過 * @param token * @param user * @return */ public static Boolean isVerify(String token, YunjiayiUser user) { //簽名祕鑰,和生成的簽名的祕鑰一模一樣 SecretKey key = generalKey(); //得到DefaultJwtParser Claims claims = Jwts.parser() //設定簽名的祕鑰 .setSigningKey(key) //設定需要解析的jwt .parseClaimsJws(token).getBody(); if (claims.get("password").equals(user.getPassword())) { return true; } return false; } /** * 由字串生成加密key * @return */ public static SecretKey generalKey() { String stringKey = Constant.JWT_SECRET; // 本地的密碼解碼 byte[] encodedKey = Base64.decodeBase64(stringKey); // 根據給定的位元組陣列使用AES加密演算法構造一個金鑰 SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES"); return key; } }