[Java web] JWT study notes

What is JWT

JWT (Json Web Tolen) is specially used to verify user identity, because http requests are stateless, each request They are all independent of each other, so other methods need to be used to mark the request status. JWT can solve this problem very well.

work process

  • Client requests login using username and password
  • The server receives the request and verifies the username and password
  • After successful verification, the server will issue a token and return the token to the client.
  • After receiving the token, the client can store it, such as putting it in a cookie.
  • Every time the client requests resources from the server, it needs to carry the token issued by the server, which can be carried in a cookie or header.
  • The server receives the request and then verifies the token contained in the client's request. If the verification is successful, it returns the request data to the client.

JWT composition

What the JWT looks like after generating the encoding

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.UQmqAUhUrpDVV2ST7mZKyLTomVfg7sYkEjmdDI5XF8Q
header

Record token type and signature algorithm ["alg":"HS256","type":"JWT"]

  • Declaration type, here is jwt

  • Declaring the encryption algorithm usually uses HMAC SHA256 directly

The complete header looks like the following JSON:

{

  'typ': 'JWT',

  'alg': 'HS256'

}

Then base64 encrypt the header (the encryption can be symmetrically decrypted), forming the first part

Payload

Carry some custom information, for example: {"id":"1"}

Define a payload:

{

  "sub": "1234567890",

  "name": "John Doe",

  "admin": true

}

Then base64 encrypt it to get the second part of Jwt

Signature

Signature ("signature", to prevent Token from being tampered with and ensure security) This part requires the base64-encrypted header and the base64-encrypted payload. The string composed of concatenation (header first) is then declared in the header. The encryption method is combined with salt secret encryption, and then constitutes the third part of jwt.

UQmqAUhUrpDVV2ST7mZKyLTomVfg7sYkEjmdDI5XF8Q

The key secret is stored on the server side. The server will generate token and verify based on this key, so it needs to be protected.

JWT usage

1. Introduce dependencies
<dependency>
    <groupId>com.auth0</groupId>
    <artifactId>java-jwt</artifactId>
    <version>3.10.3</version>
</dependency>
2. Generate token
package com.example.challengecup.utils;


import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.Map;

public class JWTUtils {
   /**
    * 生成jwt
    * 使用Hs256算法, 私匙使用固定秘钥
    *
    * @param secretKey jwt秘钥
    * @param ttlMillis jwt过期时间(毫秒)
    * @param claims    设置的信息
    * @return
    */
   public static String createJWT(String secretKey, long ttlMillis, Map<String, Object> claims) {
      // 指定签名的时候使用的签名算法,也就是header那部分
      SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;

      // 生成JWT的时间
      long expMillis = System.currentTimeMillis() + ttlMillis;
      Date exp = new Date(expMillis);

      // 设置jwt的body
      JwtBuilder builder = Jwts.builder()
              // 如果有私有声明,一定要先设置这个自己创建的私有的声明,这个是给builder的claim赋值,一旦写在标准的声明赋值之后,就是覆盖了那些标准的声明的
              .setClaims(claims)
              // 设置签名使用的签名算法和签名使用的秘钥
              .signWith(signatureAlgorithm, secretKey.getBytes(StandardCharsets.UTF_8))
              // 设置过期时间
              .setExpiration(exp);

      return builder.compact();
   }

   /**
    * Token解密
    *
    * @param secretKey jwt秘钥 此秘钥一定要保留好在服务端, 不能暴露出去, 否则sign就可以被伪造, 如果对接多个客户端建议改造成多个
    * @param token     加密后的token
    * @return
    */
   public static Claims parseJWT(String secretKey, String token) {
      // 得到DefaultJwtParser
      Claims claims = Jwts.parser()
              // 设置签名的秘钥
              .setSigningKey(secretKey.getBytes(StandardCharsets.UTF_8))
              // 设置需要解析的jwt
              .parseClaimsJws(token).getBody();
      return claims;
   }

}
3. Parse token
   public static Claims parseJWT(String secretKey, String token) {
      // 得到DefaultJwtParser
      Claims claims = Jwts.parser()
              // 设置签名的秘钥
              .setSigningKey(secretKey.getBytes(StandardCharsets.UTF_8))
              // 设置需要解析的jwt
              .parseClaimsJws(token).getBody();
      return claims;
   }

}

technical details

Every time the server receives a request, it must check the token carried in the request. Do all methods of processing requests need to add code to verify the token? Of course not. Two solutions are provided below: the filter filter provided by Servlet, and the Interceptor belonging to SpringMVC technology, a>Please see the next update for details.

Guess you like

Origin blog.csdn.net/weixin_55939638/article/details/134321512