使用JWT登錄生成token


package com.example.demo.util;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import org.apache.commons.lang3.time.DateUtils;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 *依賴:
        <dependency>
           <groupId>com.auth0</groupId>
           <artifactId>java-jwt</artifactId>
        <version>3.4.0</version>
        </dependency>
        <dependency>
        <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.7</version>
        </dependency>
 *
 *
 *
 *
 */

public abstract  class JWTUtil {
    /**
     *  JWT 由3部分組成: header(Map集合),playload(負載,也可以把它看做請求體body,也是一個map集合),signature(簽名,有header和playload加密后再跟secrect加密生成)
     *  header:有2個值,一個是類型,一個是算法,類型就是JWT,不會變,算法有2種選擇,HMAC256和RS256,基本選擇HMAC256
     *  playload:類似於post請求的請求體,是一個map集合,可以存很多很多值,如存用戶的信息
     *  signature:由header(Base64加密后)和playload(Base64加密后)再加上secrect(秘鑰生成)
     *  Base64加密是可逆的,所以存在header和playload的數據不能是敏感數據
     *
     *  playload有一些值定義:
     *
     *

     iss: jwt簽發者

     sub: jwt所面向的用戶

     aud: 接收jwt的一方

     exp: jwt的過期時間,這個過期時間必須要大於簽發時間

     nbf: 定義在什么時間之前,該jwt都是不可用的.

     iat: jwt的簽發時間

     jti: jwt的唯一身份標識,主要用來作為一次性token,從而回避重放攻擊。

     *
     * @param userId 用戶編號
     * @param secrect 秘鑰(密碼)
     * @param expireTime 過期時間單位s
     * @return
     */
    public static String getToken(String userId,String secrect,int expireTime){
        Date createDate = new Date();
        Date expireDate = DateUtils.addSeconds(createDate, expireTime);
        Map<String, Object> header = new HashMap<>();
        header.put("alg", "HS256");
        header.put("typ", "JWT");
        //token創建底層使用的是設計模式中的創建者模式,了解該模式對於下面的代碼比較容易理解
        String token = JWT.create().withHeader(header)
                .withClaim("userId", userId) //playload的一部分:withClaim底層是一個map,可以不斷使用鏈式表達式存數據
                .withIssuedAt(createDate)//創建時間 //playload的一部分
                .withExpiresAt(expireDate) //過期時間 //playload的一部分
                .sign(Algorithm.HMAC256(secrect));//生成 signature
        return token;

    }
    //如果token過期了,解析時就會報錯,所以捕捉到異常時就知道是否過期了
    public static DecodedJWT decodeToken(String token, String secretKey) {
        DecodedJWT jwt = null;

        try {
            JWTVerifier verifier = JWT.require(Algorithm.HMAC256(secretKey)).build();
            jwt = verifier.verify(token);
            return jwt;
        } catch (JWTVerificationException ex) {
            System.out.println("token 過期了");
            throw ex;
        }
    }

    //也可以通過token不需要密鑰直接獲取 DecodedJWT
    public static DecodedJWT decodedToken(String token){
        DecodedJWT decode = JWT.decode(token);
        return decode;
        //Map<String, Claim> claims = decode.getClaims();
    }
    //獲取payLoad的值
    public static Object getUserId(String token,String userId,String secrect){
        DecodedJWT decodedJWT = decodeToken(token, secrect);
        Map<String, Claim> claims = decodedJWT.getClaims();
        Claim claim = claims.get(userId);//也可以通過claims獲取其他值,具體根據存到playlaod里面的數據來取值
        return claim.asString();
    }

    public static String login(String userName,String password){


          User usr=userService.findUserByUserIdAndPassword(userName,password);
          if(null==usr){
              System.out.println("賬號或密碼錯誤");
              return null;
          }

         String token = getToken(usr.getUserId,password,86400);//1天過期

         token一旦生成,就沒法修改,只有到過期時間后,才會失效,所以可以使用redis處理,用戶每登錄一次,就生成新的token

         redisUtil.set("login:user:"+usr.getUserId,token,86400);//用戶每登錄一次就會替換一次
         return token;




        return null;
    }
    public static boolean checkToken(String userId,String token){
        if(null==token){
            return false;
        }

        String token2=redisUtil.get("login.user:"+userId);
        if(!token.equal(token2)){
            return false;
        }



        return true;
    }

}

 


免責聲明!

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



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