SoFunction
Updated on 2025-03-08

How to use threadlocal to store user identity information in springboot filter

This article mainly describes how to set jwt information to save identity information through springboot filter class to set up jwt information in filter
Process: Request->Filter->Parse the requested body information->Put it into threadlocal

Definition filter: A filter (Filter) using the Servlet specification, which is registered with the @WebFilter annotation to intercept all HTTP requests matching /api paths.

The @WebFilter("/api") annotation specifies that the filter will be applied to all requests accessing the /api path.
@Component Annotation:

@Component is an annotation of the Spring framework, indicating that JwtFilter is a Spring component that can be managed by Spring containers and supports dependency injection.
doFilter method:
The doFilter method defines how a filter intercepts and processes requests and responses entering a Servlet or Servlet container.
Method signature:

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
    throws IOException, ServletException;

This method accepts three parameters: ServletRequest request, ServletResponse response, and FilterChain chain.
It may throw an IOException or a ServletException.
Request and Response:

The first two parameters of the doFilter method represent the current request and response objects, in which you can read request data, modify requests, and responses.
Usually, at the end of the doFilter method, you need to call (request, response) to continue executing the next filter or target resource in the filter chain.

If you want to re-modify the request content, you can use HttpServletRequestWrapper. HttpServletRequestWrapper is a wrapper class that extends the HttpServletRequest interface, allowing you to modify or extend the processing of requests. The purpose of using HttpServletRequestUriWrapper (which may be a custom wrapper class inherited from HttpServletRequestWrapper) usually includes:

Modify the request URI:

You may want to modify the requested URI, but you do not want to change the original HttpServletRequest object. By using HttpServletRequestUriWrapper, you can wrap the original request and provide a modified URI.
Keep the original request unchanged:

Using wrappers can keep the original request object unchanged, while allowing you to modify certain aspects of the request at a point in the filter chain.
Filtering and preprocessing:

Before calling, you can add any preprocessing logic to the doFilter method, such as modifying the request parameters, changing the request path, adding or modifying the request header, etc.

import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import .slf4j.Slf4j;
import org.;
@WebFilter("/api")
@Component
@Slf4j
public class JwtFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) {
        // noting to do
    }
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
            throws IOException, ServletException {
        var httpRequest = (HttpServletRequest) servletRequest;
        var requestBodyPayload = ((), StandardCharsets.UTF_8);
        // parse Body parameters and store them in threadLocal management        var jwtInfo = (requestBodyPayload);
        (jwtInfo);
        // Read the body, you need to reset the body        var wrapper = new HttpServletRequestUriWrapper(httpRequest, (), requestBodyPayload);
        // Pass the request to the next filter (or finally arrive at the controller method)        (wrapper, servletResponse);
    }
    @Override
    public void destroy() {
        ();
        ();
    }
}

jwt information:

@Slf4j
@Component
public class JwtUtil {
    /** thread jwt information maintenance */
    private static final ThreadLocal<JwtInfo> REQUEST_BASE_INFO_THREAD_LOCAL = new ThreadLocal<>();
    /** Analyze jwt information */
    public static JwtInfo getJwtInfoFromReq(String requestBodyPayload) {
        var jwtInfo = new JwtInfo();
        try {
            var requestBody = (requestBodyPayload);
            ("[JwtUtil] RequestBody -> {}", requestBody);
            // parse requestBody and convert it to jwtInfo object            (("RequestId") != null ? ("RequestId").asText() : "");
            (("Region") != null ? ("Region").asText() : "");
            ("[JwtUtil] JwtInfo -> {}", jwtInfo);
        } catch (Exception e) {
            ("[JwtUtil] Parse RequestBodyInfo Error, Error Message -> {}", (), e);
        }
        return jwtInfo;
    }
    /** Get jwt information */
    public static JwtInfo getJwtInfo() {
        var jwtInfo = REQUEST_BASE_INFO_THREAD_LOCAL.get();
        if ((jwtInfo)) {
            final var requestAttributes = (ServletRequestAttributes) ();
            if ((requestAttributes)) {
                var requestBodyPayload = "";
                try {
                    requestBodyPayload = (().getInputStream(),
                            StandardCharsets.UTF_8);
                } catch (Exception e) {
                    ("[JwtUtil] Parse RequestBodyInfo Error, Error Message -> {}", ());
                }
                jwtInfo = getJwtInfoFromReq(requestBodyPayload);
                setJwtInfo(jwtInfo);
            }
        }
        return jwtInfo;
    }
    /** Save jwt information into threadLocal */
    public static void setJwtInfo(JwtInfo jwtInfo) {
        REQUEST_BASE_INFO_THREAD_LOCAL.set(jwtInfo);
        // Write traceId to log variable        ("traceId", ());
    }
    public static void setJwtInfo(String appId, String ownerUin) {
        var jwtInfo = new ();
        (().toString());
        setJwtInfo(jwtInfo);
    }
    /** Remove jwt information from threadLocal */
    public static void removeJwtInfo() {
        REQUEST_BASE_INFO_THREAD_LOCAL.remove();
    }
    @Data
    public static class JwtInfo {
        @JsonPropertyDescription("RequestId")
        private String requestId;
        @JsonPropertyDescription("Requested Region")
        private String region;
    }
}

Get the content in jwt and send other http requests:

   public static JsonNode sendHttpRequest(String method, String action, String url, Map<String, Object> body)
            throws IOException, InterruptedException {
        // Set common parameters        var jwtInfo = ();
        if (jwtInfo != null) {
            ("RequestId", ());
            ("AppId", (()));
            ("Uin", ());
            ("Region", ());
        }
        // Set action        ("Action", action);
        // Send http request and get the request result         responseInfo = switch (method) {
            case "GET" -> (url, (body));
            case "POST" -> (url, (body), new HashMap<>(2));
            default -> new ();
        };
        // Check the results returned by Api3 format and parse        var jsonResponse = (()).get("Response");
        var jsonError = ("Error");
        if (jsonError != null) {
            var errorCode = ("Code").asText();
            var errorMessage = ("Message").asText();
            throw new ApiException(ErrorCode.INTERNAL_ERROR,
                    ("Error code: [%s], Error message: [%s]", errorCode, errorMessage));
        }
        return jsonResponse;
    }

This is the article about using threadlocal to store user identity information in springboot in filter. For more related contents of threadlocal to store user identity information, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!