SpringBoot拦截器中获取token中的用户信息并通过注解可以在任何一个Controller上获取到用户基本信息
前端调用后端Controller方法时,进入Controller方法后,经常需要获取当前登录用户的信息,便于一些后续的用户操作(比如保存时需要自动填入当前登录用户的用户名)。
通常的做法是,前端将token信息放入请求头中,后端拿到请求头中的token后,再将token解析成用户信息。
解决方案 token解析工具类方法
校验token有效性:boolean isValid = tokenUtils.isValid(token);
解析token为User:User user = tokenUtils.getUserInfoByToken(token);
直接在需要使用用户信息的地方调用token解析方法获取User对象。
WebMvcConfigurer + HandlerInterceptor + HandlerMethodArgumentResolver
Spring内部的一种配置方法,通过用java代码代替xml配置Bean,可以通过实现WebMvcConfigurer接口自定义一些MVC相关的Handler,Interceptor等。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 @Configuration public class SecurityAutoConfiguration implements WebMvcConfigurer { @Override public void addInterceptors (InterceptorRegistry registry) { registry.addInterceptor(getAuthInterceptor()).addPathPatterns("/**" ); } @Bean public AuthInterceptor getAuthInterceptor () { return new AuthInterceptor(); } @Bean public CurrentUserMethodArgumentResolver currentUserMethodArgumentResolver () { return new CurrentUserMethodArgumentResolver(); } @Override public void addArgumentResolvers (List argumentResolvers) { argumentResolvers.add(currentUserMethodArgumentResolver()); } }
自定义HandlerInterceptor进行权限校验,token解析
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 public class AuthInterceptor implements HandlerInterceptor { @Override public boolean preHandle (HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String tokenId = request.getHeader(CommonDefs.AUTHORIZATION); if (!StringUtils.hasLength(tokenId)) { return false ; } boolean isValid = tokenUtils.isValid(token); if (!isValid) { return false ; } User user = tokenUtils.getUserInfoByToken(token); if (user == null ) { return false ; } request.setAttribute("current_user" , user); return true ; } }
自定义@CurrentUser注解,并加入到controller接口中
1 2 3 4 5 6 @Target({ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface CurrentUser { String value () default "current_user" ; }
1 2 3 4 5 6 @GetMapping("/getUserInfo") @ApiOperation(value = "查询用户信息") public Result getUserInfo (@ApiIgnore @CurrentUser User user) { return Result.ok(user); }
自定义HandlerMethodArgumentResolver,将request中的User传给@CurrentUser
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 public class CurrentUserMethodArgumentResolver implements HandlerMethodArgumentResolver { public CurrentUserMethodArgumentResolver () { } @Override public boolean supportsParameter (MethodParameter parameter) { return parameter.hasParameterAnnotation(CurrentUser.class); } @Override public Object resolveArgument (MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception { CurrentUser currentUserAnnotation = (CurrentUser)parameter.getParameterAnnotation(CurrentUser.class); return webRequest.getAttribute(currentUserAnnotation.value(), 0 ); } }
如果没生效,排查一下 implements WebMvcConfigurer 的配置类 是否将解析器注入到了SpirngMVC
如果没有 可参考
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 import com.chentawen.springbootall.config.annotation.UserIdResolver;import org.springframework.context.annotation.Configuration;import org.springframework.web.method.support.HandlerMethodArgumentResolver;import org.springframework.web.servlet.config.annotation.InterceptorRegistry;import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;import java.util.List;@Configuration public class IntercaptorConfig implements WebMvcConfigurer { @Override public void addArgumentResolvers (List<HandlerMethodArgumentResolver> resolvers) { resolvers.add(new UserIdResolver()); } }