Spring Boot中如何为HandlerMethodArgumentResolver从请求头获取JwtAuthenticationToken
解决方案
完全可以直接获取已经解析好的JwtAuthenticationToken,不需要自己手动解析Authorization头的Bearer字符串。Spring Security完成JWT认证后,已经将生成的JwtAuthenticationToken存入SecurityContextHolder,你直接从上下文取即可。
实现步骤
1. 自定义HandlerMethodArgumentResolver
你可以选择两种实现方向,按需选择:
方向1:直接注入JwtAuthenticationToken
实现解析器,直接将JwtAuthenticationToken注入到控制器参数:
import org.springframework.core.MethodParameter; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken; import org.springframework.web.bind.support.WebDataBinderFactory; import org.springframework.web.context.request.NativeWebRequest; import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.method.support.ModelAndViewContainer; public class JwtAuthenticationTokenArgumentResolver implements HandlerMethodArgumentResolver { @Override public boolean supportsParameter(MethodParameter parameter) { return parameter.getParameterType().equals(JwtAuthenticationToken.class); } @Override public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception { var authentication = SecurityContextHolder.getContext().getAuthentication(); if (authentication instanceof JwtAuthenticationToken jwtToken) { return jwtToken; } // 可根据业务需求替换为自定义未认证异常 throw new RuntimeException("用户未认证"); } }
方向2:直接注入解析好的用户UID(更推荐,减少重复代码)
先自定义一个标识注解:
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target(ElementType.PARAMETER) @Retention(RetentionPolicy.RUNTIME) public @interface CurrentUid { }
再实现对应的参数解析器,把你原有的getUidFromToken逻辑搬到这里:
import org.springframework.core.MethodParameter; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken; import org.springframework.web.bind.support.WebDataBinderFactory; import org.springframework.web.context.request.NativeWebRequest; import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.method.support.ModelAndViewContainer; public class CurrentUidArgumentResolver implements HandlerMethodArgumentResolver { @Override public boolean supportsParameter(MethodParameter parameter) { return parameter.hasParameterAnnotation(CurrentUid.class) && parameter.getParameterType().equals(String.class); } @Override public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception { var authentication = SecurityContextHolder.getContext().getAuthentication(); if (authentication instanceof JwtAuthenticationToken jwtToken) { // 替换为你原有提取UID的逻辑,比如从指定claim取值 return jwtToken.getToken().getClaim("uid"); } throw new RuntimeException("用户未认证"); } }
2. 注册参数解析器
把自定义的解析器注册到Spring MVC配置中:
import org.springframework.context.annotation.Configuration; import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import java.util.List; @Configuration public class WebConfig implements WebMvcConfigurer { @Override public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) { // 按需添加你自己实现的解析器 // resolvers.add(new JwtAuthenticationTokenArgumentResolver()); resolvers.add(new CurrentUidArgumentResolver()); } }
3. 控制器使用示例
如果用方向2,控制器代码可以简化为:
public ResponseEntity<String> getUserProfile(@CurrentUid String uid) { // 直接拿到解析好的uid,不需要再重复处理token // rest of the code }
注意事项
- 上述代码适用于Servlet环境的Spring Boot项目,如果是WebFlux反应式项目,需要替换为
ReactiveSecurityContextHolder异步获取认证信息 - 确保对应接口已经配置Spring Security认证规则,未经过认证的接口无法拿到有效的
JwtAuthenticationToken
内容的提问来源于stack exchange,提问作者Fam
相关产品推荐
相关产品推荐

