利用JWT生成Token

開篇

實現Token的方式有很多,本篇介紹的是利用Json Web Token(JWT)生成的Token.JWT生成的Token有什麼好處呢?

  • 安全性比較高,加上密匙加密而且支持多種算法。
  • 攜帶的信息是自定義的,而且可以做到驗證token是否過期。
  • 驗證信息可以由前端保存,後端不需要爲保存token消耗內存。

本篇分3部分進行講解。

    1. 什麼是JWT
    1. JWT的代碼實現,代碼將JWT封裝成兩個工具類,可以直接調用。
    1. 總結

如果原理很難懂,沒關係。可以直接看JWT的代碼實現。代碼已經上傳github。已經對代碼進行封裝成工具類。可以直接使用。

什麼是JWT

JSON Web Token 簡稱JWT。
一個JWT實際上就是一個字符串,它由三部分組成,頭部載荷簽名
JWT生成的token是這樣的

eyJpc3MiOiJKb2huI.eyJpc3MiOiJ.Kb2huIFd1IEp

生成的token,是3段,用.連接。下面有解釋。

頭部

用於描述關於該JWT的最基本的信息,例如其類型以及簽名所用的算法等。這也可以被表示成一個JSON對象。
例如:

{
   "typ": "JWT",
  "alg": "HS256"
}

載荷

其實就是自定義的數據,一般存儲用戶Id,過期時間等信息。也就是JWT的核心所在,因爲這些數據就是使後端知道此token是哪個用戶已經登錄的憑證。而且這些數據是存在token裏面的,由前端攜帶,所以後端幾乎不需要保存任何數據。
例如:

{
  "uid": "xxxxidid",  //用戶id
  "exp": "12121212"  //過期時間
}

簽名

簽名其實就是:
1.頭部和載荷各自base64加密後用.連接起來,然後就形成了xxx.xx的前兩段token。
2.最後一段token的形成是,前兩段加入一個密匙用HS256算法或者其他算法加密形成。
3. 所以token3段的形成就是在簽名處形成的。

JWT的原理參考文章

代碼實現

1.看代碼前一定要知道JWT是由頭部載荷簽名組成。
2.代碼已上傳github,希望點個贊
3. 代碼將JWT封裝成兩個工具類,可以直接調用。

需要下載的jar包

<dependency>
            <groupId>com.nimbusds</groupId>
            <artifactId>nimbus-jose-jwt</artifactId>
            <version>4.23</version>
</dependency>

生成token

 /**
     * 1.創建一個32-byte的密匙
     */

    private static final byte[] secret = "geiwodiangasfdjsikolkjikolkijswe".getBytes();


    //生成一個token
    public static String creatToken(Map<String,Object> payloadMap) throws JOSEException {

        //3.先建立一個頭部Header
        /**
         * JWSHeader參數:1.加密算法法則,2.類型,3.。。。。。。。
         * 一般只需要傳入加密算法法則就可以。
         * 這裏則採用HS256
         *
         * JWSAlgorithm類裏面有所有的加密算法法則,直接調用。
         */
        JWSHeader jwsHeader = new JWSHeader(JWSAlgorithm.HS256);

        //建立一個載荷Payload
        Payload payload = new Payload(new JSONObject(payloadMap));

        //將頭部和載荷結合在一起
        JWSObject jwsObject = new JWSObject(jwsHeader, payload);

        //建立一個密匙

        JWSSigner jwsSigner = new MACSigner(secret);

        //簽名
        jwsObject.sign(jwsSigner);

        //生成token
        return jwsObject.serialize();
    }

驗證token

 //解析一個token

    public static Map<String,Object> valid(String token) throws ParseException, JOSEException {

//        解析token

        JWSObject jwsObject = JWSObject.parse(token);

        //獲取到載荷
        Payload payload=jwsObject.getPayload();

        //建立一個解鎖密匙
        JWSVerifier jwsVerifier = new MACVerifier(secret);

        Map<String, Object> resultMap = new HashMap<>();
        //判斷token
        if (jwsObject.verify(jwsVerifier)) {
            resultMap.put("Result", 0);
            //載荷的數據解析成json對象。
            JSONObject jsonObject = payload.toJSONObject();
            resultMap.put("data", jsonObject);

            //判斷token是否過期
            if (jsonObject.containsKey("exp")) {
                Long expTime = Long.valueOf(jsonObject.get("exp").toString());
                Long nowTime = new Date().getTime();
                //判斷是否過期
                if (nowTime > expTime) {
                    //已經過期
                    resultMap.clear();
                    resultMap.put("Result", 2);

                }
            }
        }else {
            resultMap.put("Result", 1);
        }
        return resultMap;

    }

調用的業務邏輯

//生成token的業務邏輯
    public static String TokenTest(String uid) {
        //獲取生成token

        Map<String, Object> map = new HashMap<>();

        //建立載荷,這些數據根據業務,自己定義。
        map.put("uid", uid);
        //生成時間
        map.put("sta", new Date().getTime());
        //過期時間
        map.put("exp", new Date().getTime()+6);
        try {
            String token = TokenUtils.creatToken(map);
            System.out.println("token="+token);
            return token;
        } catch (JOSEException e) {
            System.out.println("生成token失敗");
            e.printStackTrace();
        }
        return null;

    }

    //處理解析的業務邏輯
    public static void ValidToken(String token) {
        //解析token
        try {
            if (token != null) {

                Map<String, Object> validMap = TokenUtils.valid(token);
                int i = (int) validMap.get("Result");
                if (i == 0) {
                    System.out.println("token解析成功");
                    JSONObject jsonObject = (JSONObject) validMap.get("data");
                    System.out.println("uid是" + jsonObject.get("uid"));
                    System.out.println("sta是"+jsonObject.get("sta"));
                    System.out.println("exp是"+jsonObject.get("exp"));
                } else if (i == 2) {
                    System.out.println("token已經過期");
                }
            }
        } catch (ParseException e) {
            e.printStackTrace();
        } catch (JOSEException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] ages) {
        //獲取token
        String uid = "kkksuejrmf";
        String token = TokenTest(uid);
        //解析token
        ValidToken(token);
    }

總結

JWT 的實踐其實還是挺簡單。安全性也是得到了保證,後端只需要保存着密匙,其他數據可以保存在token,由前端攜帶,這樣可以減低後端的內存消耗。
雖然token是加密的,但是攜帶的驗證數據還是不要是敏感數據.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章