实现一个自定义解析器来解析 HTTP 请求中的 JWT Token

259 阅读3分钟

参数解析器(Parameter Resolver)是Web框架中用于将HTTP请求参数转换为对应的Java对象的组件,可以简化业务代码中对请求参数的处理。

在Spring MVC中,参数解析器是通过实现HandlerMethodArgumentResolver接口来定义的。当一个请求到达控制层后,Spring会遍历已经注册的参数解析器来查找合适的解析器来解析请求参数并绑定到方法参数上。如果找到了匹配的解析器,Spring就会调用该解析器的resolveArgument方法来进行参数解析,并返回解析后的对象作为方法参数传递进来。如果没有找到匹配的解析器,则会抛出异常提示参数解析失败。

常见的参数解析器包括:

  • RequestBody 解析器:将HTTP请求体中的JSON/XML字符串转换为Java对象。
  • RequestParam 解析器:将HTTP查询参数(即URL中的参数)转换为Java对象。
  • PathVariable 解析器:将HTTP路径变量转换为Java对象。
  • Custom Argument Resolver(自定义参数解析器):根据业务场景,自己定义媒介类型(比如bearer token/token、分页信息等)的参数解析器。

使用参数解析器可以减少业务代码对请求参数的处理和转换,提高代码复用性和减少冗余代码,使程序更加简洁和易于维护。

image.png

首先,需要实现Spring的HandlerMethodArgumentResolver接口,该接口有两个方法需要实现:

  • supportsParameter: 判断当前参数是否需要由自定义解析器解析。
  • resolveArgument: 解析请求参数并返回对应的对象。

以下是实现一个自定义解析器来解析 HTTP 请求中的 JWT Token ,具体代码如下:

public class JwtTokenArgumentResolver implements HandlerMethodArgumentResolver {

    private static final String AUTHORIZATION_HEADER = "Authorization";
    private static final String BEARER_PREFIX = "Bearer ";

    @Override
    public boolean supportsParameter(MethodParameter methodParameter) {
        return methodParameter.getParameterAnnotation(JwtToken.class) != null;
    }

    @Override
    public Object resolveArgument(
            MethodParameter parameter,
            ModelAndViewContainer mavContainer,
            NativeWebRequest webRequest,
            WebDataBinderFactory binderFactory) throws Exception {
        
        HttpServletRequest httpServletRequest = webRequest.getNativeRequest(HttpServletRequest.class);
        if (httpServletRequest == null) {
            throw new IllegalArgumentException("HttpServletRequest is null");
        }
        
        String authorizationHeader = httpServletRequest.getHeader(AUTHORIZATION_HEADER);
        if (StringUtils.isBlank(authorizationHeader)) {
            throw new UnauthorizedException("JWT token not found in request header");
        }
        
        String jwtToken = StringUtils.removeStart(authorizationHeader, BEARER_PREFIX);
        if (StringUtils.isBlank(jwtToken)) {
            throw new UnauthorizedException("JWT token not found in request header");
        }
        
        // 将解析后的 JWT Token 赋值到对应的参数上
        return decodeJwtToken(jwtToken, parameter.getParameterType());
    }

    private Object decodeJwtToken(String jwtToken, Class<?> parameterType) {
        // 解码 JWT Token 并返回参数对应的对象
        // ...
    }
}

上述代码中,JwtTokenArgumentResolver类实现了Spring的HandlerMethodArgumentResolver接口,并重写了其中的两个方法。其中,supportsParameter方法判断当前参数类型是否被@JwtToken注解标识,如果被标识则返回true表示由该自定义解析器解析。resolveArgument方法用于解析 HTTP 请求中的 JWT Token,将其转换为对应的Java对象并返回,供后续业务代码使用。

在完成自定义解析器类的编写后,需要通过Spring配置将其注册到Spring容器中:

@Configuration
public class AppConfig implements WebMvcConfigurer {

    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
        argumentResolvers.add(new JwtTokenArgumentResolver());
    }
}

上述代码通过addArgumentResolvers方法将自定义解析器JwtTokenArgumentResolver加入到Spring的参数解析器列表中,从而实现对HTTP请求参数的解析。