JWT工具類


一、工具類代碼

/*
* 總的來說,工具類中有三個方法
* 獲取JwtToken,獲取JwtToken中封裝的信息,判斷JwtToken是否存在
* 1. encode(),參數是=簽發人,存在時間,一些其他的信息=。返回值是JwtToken對應的字符串
* 2. decode(),參數是=JwtToken=。返回值是荷載部分的鍵值對
* 3. isVerify(),參數是=JwtToken=。返回值是這個JwtToken是否存在
* */
public class JwtUtil {
    // 創建默認的秘鑰和算法,供無參的構造方法使用
    private static final String defaultbase64EncodedSecretKey = "xxx";
    private static final SignatureAlgorithm defaultsignatureAlgorithm = SignatureAlgorithm.HS256;

    public JwtUtil() {
        this(defaultbase64EncodedSecretKey, defaultsignatureAlgorithm); // 調用本類的構造方法
    }

    private final String base64EncodedSecretKey;
    private final SignatureAlgorithm signatureAlgorithm;

    public JwtUtil(String secretKey, SignatureAlgorithm signatureAlgorithm) {
        this.base64EncodedSecretKey = Base64.encodeBase64String(secretKey.getBytes()); // 這樣給成員變量賦值是為了讓成員方法也能使用
        this.signatureAlgorithm = signatureAlgorithm;
    }

    /*
     * 這里就是產生jwt字符串的地方 jwt字符串包括三個部分 1. header -當前字符串的類型,一般都是“JWT”
     * -哪種算法加密,“HS256”或者其他的加密算法 所以一般都是固定的,沒有什么變化 2. payload 一般有四個最常見的標准字段(下面有)
     * iat:簽發時間,也就是這個jwt什么時候生成的 jti:JWT的唯一標識 iss:簽發人,一般都是username或者userId exp:過期時間
     *
     */
    public String encode(String iss, long ttlMillis, Map<String, Object> claims) {
        // iss簽發人,ttlMillis生存時間,claims是指還想要在jwt中存儲的一些非隱私信息
        if (claims == null) {
            claims = new HashMap<>();
        }
        long nowMillis = System.currentTimeMillis();

        JwtBuilder builder = Jwts.builder().setClaims(claims).setId(UUID.randomUUID().toString())// 2.
             // 這個是JWT的唯一標識,一般設置成唯一的,這個方法可以生成唯一標識
                .setIssuedAt(new Date(nowMillis))// 1. 這個地方就是以毫秒為單位,換算當前系統時間生成的iat
                .setSubject(iss)// 3. 簽發人,也就是JWT是給誰的(邏輯上一般都是username或者userId)
                .signWith(signatureAlgorithm, base64EncodedSecretKey);// 這個地方是生成jwt使用的算法和秘鑰
        if (ttlMillis >= 0) {
            long expMillis = nowMillis + ttlMillis;
            Date exp = new Date(expMillis);// 4. 過期時間,這個也是使用毫秒生成的,使用當前時間+前面傳入的持續時間生成
            builder.setExpiration(exp);
        }
        return builder.compact();
    }

    // 相當於encode的方向,傳入jwtToken生成對應的username和password等字段。Claim就是一個map
    // 也就是拿到荷載部分所有的鍵值對
    public Claims decode(String jwtToken) {

        // 得到 DefaultJwtParser
        return Jwts.parser()
                // 設置簽名的秘鑰
                .setSigningKey(base64EncodedSecretKey) // 使用成員變量的值 // 設置需要解析的 jwt
                .parseClaimsJws(jwtToken).getBody();
    }

    // 判斷jwtToken是否合法
    public boolean isVerify(String jwtToken) {
        // 這個是官方的校驗規則,這里只寫了一個”校驗算法“,可以自己加
        Algorithm algorithm = null;
        switch (signatureAlgorithm) {
        case HS256:
            algorithm = Algorithm.HMAC256(Base64.decodeBase64(base64EncodedSecretKey));
            break;
        default:
            throw new RuntimeException("不支持該算法");
        }
        JWTVerifier verifier = JWT.require(algorithm).build();
        verifier.verify(jwtToken); // 校驗不通過會拋出異常
        // 判斷合法的標准:1. 頭部和荷載部分沒有篡改過。2. 沒有過期
        return true;
    }

    public static void main(String[] args) {
        JwtUtil util = new JwtUtil("tom", SignatureAlgorithm.HS256);
        // 以tom作為秘鑰,以HS256加密
        Map<String, Object> map = new HashMap<>();
        map.put("username", "tom");
        map.put("password", "123456");
        map.put("age", 20);

        String jwtToken = util.encode("tom", 30000, map);

        System.out.println(jwtToken);
        util.decode(jwtToken).entrySet().forEach((entry) -> {
            System.out.println(entry.getKey() + ": " + entry.getValue());
        });
    }
}

如果encode的第二個參數ttlMillis為負數,表示永遠不會過期。

二、工具類的使用

生成jwt

@PostMapping(value = "/applogin")
    public JSONObject loginAccount(@RequestBody JSONObject json) throws Exception {
        JSONObject result = new JSONObject();
        String username = json.getString("username");
        String password = json.getString("password");

        // 獲取用戶信息
        User user = userService.getUser(username, password);
        if (user != null) {
            user.setPassword(null);    // 清除密碼,即密碼信息不返回給前端
            result.put("userInfo", user);

            // 生成token
            JwtUtil jwtUtil = new JwtUtil();
            Map<String, Object> chaim = new HashMap<>();
            chaim.put("username", username);
            String jwtToken = jwtUtil.encode(username, -1, chaim); // 參數一為簽發人,第二個參數為過期時間,第三個參數為payload
            result.put("result", true);
            result.put("token", jwtToken);
        } else {
            result.put("result", false);
            result.put("msg", "用戶名或密碼錯誤");
        }
        return result;
    }

從jwt中獲取username

public class BaseController {

    @Resource
    private IUserService userService;

    public User getSessionUser() {
        Subject subject = SecurityUtils.getSubject();
        String jwtToken = (String) subject.getPrincipal();
        JwtUtil jwtUtil = new JwtUtil();
        Claims decode = jwtUtil.decode(jwtToken);
        String phone = decode.get("username", String.class);
        QueryWrapper<User> wrapper = new QueryWrapper<User>();
        wrapper.eq("user_phone", phone).or().eq("user_no", phone);
        User user = userService.getOne(wrapper);
        return user;
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM