jwt生成token和token解析基礎

niewj發表於2022-06-27

1.jwt結構

jwt生成到客戶端(瀏覽器)的token包含"."分開的三個部分:

  • header(Base64Url編碼過的)
  • payload(Base64Url編碼過的)
  • signature

形如:xxxxx.yyyyy.zzzzz

1.1 例子:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoiYW5keSIsImV4cCI6MTY1NTg5NzEwMCwiYWdlIjozMH0.32hfc-oBxGg2Lgk3QR48HCbadsbOfCUxexw9aiQ_FQk

拆為3部分:

  • eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.(header)
  • eyJuYW1lIjoiYW5keSIsImV4cCI6MTY1NTg5NzEwMCwiYWdlIjozMH0.(payload)
  • 32hfc-oBxGg2Lgk3QR48HCbadsbOfCUxexw9aiQ_FQk(signature)

2.header+payload+signature介紹

2.1 header

上面的header部分:eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9
base64Url解碼後:

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

通常說明token的型別、生成token所使用的的演算法

The header typically consists of two parts: the type of the token, which is JWT, and the signing algorithm being used, such as HMAC SHA256 or RSA.

2.2 Payload

上面的Payload部分:eyJuYW1lIjoiYW5keSIsImV4cCI6MTY1NTg5NzEwMCwiYWdlIjozMH0
base64Url解碼後:

{
  "name": "andy",
  "exp": 1655897100,
  "age": 30
}

通常是要客戶端請求時帶貨的內容(比如使用者名稱,比如是否是管理員等,server端生成的時候可以定義內容,形式如map)

The second part of the token is the payload, which contains the claims. Claims are statements about an entity (typically, the user) and additional data. There are three types of claims: registered, public, and private claims.

2.3 Signature

上面的Signature部分:32hfc-oBxGg2Lgk3QR48HCbadsbOfCUxexw9aiQ_FQk
它是用來驗籤的, 驗證是否被客戶端修改過,它的生成邏輯如下:
就是使用header部分的base64Url、payload部分的base64Url部分、小圓點、以及你的私鑰密碼,使用指定的演算法生成的;因為有密碼, 所以是安全的,這也是密碼要保護好的原因。

  • 計算邏輯如下:

    HMACSHA256(
    base64UrlEncode(header) + "." + base64UrlEncode(payload),
    12345
    )

3. java測試用例

    /**
     * JWT加密生成token, payload中儲存 name/age
     */
    @Test
    public void testJwtToken() {
        // 加密祕鑰
        final String SECRET = "12345";

        Calendar c = Calendar.getInstance();
        c.add(Calendar.HOUR, 2);

        String token = JWT.create().withClaim("name", "andy")
                .withClaim("age", 30)
                .withExpiresAt(c.getTime())
                .sign(Algorithm.HMAC256(SECRET));

        System.out.println(token);
    }

    /**
     * JWT解密生成token, 讀取payload中儲存的 name/age
     */
    @Test
    public void testJwtVerify() {

        String jwtToken = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoiYW5keSIsImV4cCI6MTY1NTg4ODk3MiwiYWdlIjozMH0.LU4AQJkld03kDhatkiiArSJI4liGiANArTvoyswzk5I";
        final String SECRET = "12345";

        JWTVerifier verifier = JWT.require(Algorithm.HMAC256(SECRET)).build();
        DecodedJWT decodedJWT = verifier.verify(jwtToken);
        Claim name = decodedJWT.getClaim("name");
        Claim age = decodedJWT.getClaim("age");
        System.out.println(name);
        System.out.println(age);

    }

相關文章