1. 程式人生 > 實用技巧 >JWT相關整合

JWT相關整合

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;
    }

}