This is the 26th day of my participation in the First Challenge 2022

How do I use JWT to achieve authorized access to the API

What is the JWT

JWT(JSON Web Token) is an open standard (RFC 7519) that defines a compact and independent way to securely transfer information between systems using JSON as an object, with the assurance that the information transferred will not be tampered with.

JWT is typically used in two scenarios:

  • Authorization. This is the most common JWT usage scenario. Once the user is logged in, each subsequent request will contain a JWT as a token for that user to access the resource.
  • Information exchange. Information can be securely transferred between systems using JWT, whose features allow recipients to verify that the received content has not been tampered with.

This article discusses the first point, how to use JWT to implement authorized access to the API. In this way, only authorized users can call the API.

The structure of the JWT

JWT consists of three parts, using. Separated.

Header

The first part, the Header, usually consists of two parts: the type of token, JWT, and the encryption algorithm used.

{
  "alg": "HS256",
  "typ": "JWT"
}
Copy the code

When Base64 is encrypted, it becomes:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
Copy the code

Payload

The second part is Payload, which can place customized information, expiration time, issuer, etc.

{
  "sub": "1234567890",
  "name": "John Doe",
  "iat": 1516239022
}
Copy the code

When Base64 is encrypted, it becomes:

eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ
Copy the code

Signature

The third part is Signature, and four parts of information are required to calculate this Signature:

  • HeaderAlgorithm information in the
  • Header
  • Payload
  • A custom secret key

After receiving JWT, the same information is used to calculate the signature again, and then the signature is compared with the signature in JWT. If the signature is different, it indicates that the content in JWT is tampered.

Decoded JWT

You code all three parts and put them together to get JWT.

It is important to note that the content of JWT is not encrypted, just plain Base64 encoding. That is, once a JWT is compromised, the information inside it can be easily accessed, so you should not use JWT to store any sensitive information.

How does JWT work

  1. The application or client requests authorization from the authorization server. The authorization server can be a separate application or integrated with the API in the same application.
  2. The authorization server returns a JWT to the application.
  3. The application puts the JWT into the request (usually placedHTTPtheAuthorizationHead)
  4. Upon receiving the request, the server validates the JWT and executes the corresponding logic.

Use JWT in JAVA

Introduction of depend on

<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
</dependency>
Copy the code

A library called JJWT(Java JWT) is used here.

JWT Service

Generate JWT

public String generateToken(String payload) {
        return Jwts.builder()
                .setSubject(payload)
                .setExpiration(new Date(System.currentTimeMillis() + 10000))
                .signWith(SignatureAlgorithm.HS256, SECRET_KEY)
                .compact();
    }
Copy the code
  • The expiration time is set to 10 seconds, so the generated JWT will only pass validation in 10 seconds.
  • You need to provide a custom secret key.

Decoding the JWT

public String parseToken(String jwt) {
        return Jwts.parser()
                .setSigningKey(SECRET_KEY)
                .parseClaimsJws(jwt)
                .getBody()
                .getSubject();
    }
Copy the code

The signature of the JWT is checked for decoding, so the secret key is required.

Verify the JWT

public boolean isTokenValid(String jwt) {
        try {
            parseToken(jwt);
        } catch (Throwable e) {
            return false;
        }
        return true;
    }
Copy the code

JWT does not provide a way to determine whether a JWT is valid, but an exception is thrown when an invalid JWT is decoded, so you can catch the exception to determine whether it is valid.

Registration/Login

@GetMapping("/registration")
    public String register(@RequestParam String username, HttpServletResponse response) {
        String jwt = jwtService.generateToken(username);
        response.setHeader(JWT_HEADER_NAME, jwt);

        return String.format("JWT for %s :\n%s", username, jwt);
    }
Copy the code

  • You need to provide such a registration or login entry for users who have not yet acquired a JWT to obtain it.
  • After obtaining the JWT in the response, include the JWT in subsequent requests, which is placed in the requestAuthorizationHeads.

Verify the JWT

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        HttpServletResponse httpServletResponse = (HttpServletResponse) response;

        String jwt = httpServletRequest.getHeader(JWT_HEADER_NAME);
        if (WHITE_LIST.contains(httpServletRequest.getRequestURI())) {
            chain.doFilter(request, response);
        } else if (isTokenValid(jwt)) {
            updateToken(httpServletResponse, jwt);
            chain.doFilter(request, response);
        } else {
            httpServletResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED);
        }
    }

private void updateToken(HttpServletResponse httpServletResponse, String jwt) {
        String payload = jwtService.parseToken(jwt);
        String newToken = jwtService.generateToken(payload);
        httpServletResponse.setHeader(JWT_HEADER_NAME, newToken);
    }
Copy the code

  • Put the validation operations inFilterIn this way, other business code will not feel the presence of JWT except for the login entry.
  • Place the login entry inWHITE_LISTSkip the validation of these entries.
  • JWT needs to be refreshed. If JWT is legal, the same should be usedPayloadTo generate a new JWT so that the new JWT will have a new expiration time, use this operation to refresh the JWT in case it expires.
  • If you are usingFilter, then the refresh operation must be calleddoFilter()Before, because you can’t change it after you call itresponse.

API

private final static String JWT_HEADER_NAME = "Authorization";

    @GetMapping("/api")
    public String testApi(HttpServletRequest request, HttpServletResponse response) {
        String oldJwt = request.getHeader(JWT_HEADER_NAME);
        String newJwt = response.getHeader(JWT_HEADER_NAME);

        return String.format("Your old JWT is:\n%s \nYour new JWT is:\n%s\n", oldJwt, newJwt);
    }
Copy the code

The API is now under the protection of the JWT. The API can be completely unaware of the existence of the JWT, and can also proactively obtain and decode the JWT to get information in the JWT. As shown above.

Demo:github.com/Beginner258…

Reference: jwt. IO /