个人随笔
目录
Springboot项目通过拦截器来检查登录信息以及将登录信息设置到上下文中的方法
2025-08-06 11:53:03

需求很简单,就是Controller层不需要再从request中获取请求头的token,再根据token去redis或者数据库获取用户信息判断用户是否登录。怎么实现呢?

1、先实现一个未授权的异常

当然这个异常可有可无,这里只是为了后续在拦截器中如果检测不通过就直接抛出这个异常

  1. public class UnauthorizedException extends RuntimeException {
  2. public UnauthorizedException(String message) {
  3. super(message);
  4. }
  5. }

2、实现一个拦截器

这里就是根据请求头的token从redis获取用户信息设置到上下文中

  1. @Component
  2. public class TokenInterceptor implements HandlerInterceptor {
  3. @Autowired
  4. private RedisTemplate<String, Object> redisTemplate;
  5. @Override
  6. public boolean preHandle(HttpServletRequest request,
  7. HttpServletResponse response,
  8. Object handler) {
  9. String token = request.getHeader("Authorization");
  10. if (StringUtils.isEmpty(token)) {
  11. throw new UnauthorizedException("缺少认证令牌");
  12. }
  13. String userId = JwtUtil.parseToken(token);
  14. String redisKey = "user:info:" + userId;
  15. UserDTO user = (UserDTO) redisTemplate.opsForValue().get(redisKey);
  16. UserContext.setCurrentUser(user);
  17. return true;
  18. }
  19. @Override
  20. public void afterCompletion(HttpServletRequest request,
  21. HttpServletResponse response,
  22. Object handler, Exception ex) {
  23. UserContext.remove(); // 防止内存泄漏
  24. }
  25. }

3、实现一个上下文

这里就简单的用ThreadLocal来实现即可,要注意在拦截器中把这个线程remove掉。

  1. public class UserContext {
  2. private static final ThreadLocal<UserDTO> USER_HOLDER = new ThreadLocal<>();
  3. public static void setCurrentUser(UserDTO user) {
  4. USER_HOLDER.set(user);
  5. }
  6. public static UserDTO getCurrentUser() {
  7. return USER_HOLDER.get();
  8. }
  9. public static void remove() {
  10. USER_HOLDER.remove();
  11. }
  12. }

4、配置拦截器生效

  1. @Configuration
  2. public class WebMvcConfig implements WebMvcConfigurer {
  3. @Autowired
  4. private TokenInterceptor tokenInterceptor;
  5. @Override
  6. public void addInterceptors(InterceptorRegistry registry) {
  7. registry.addInterceptor(tokenInterceptor)
  8. .addPathPatterns("/**")
  9. .excludePathPatterns("/login");
  10. }
  11. }

这里一定要注意,里面配置的路径不能包括springboot配置文件的server.servlet.context-path.

5、这里再实现一个全局异常

  1. @RestControllerAdvice
  2. public class GlobalExceptionHandler {
  3. @ExceptionHandler(UnauthorizedException.class)
  4. public ResponseEntity<Result<String>> handleUnauthorized(UnauthorizedException e) {
  5. return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
  6. .body(Result.error(401, e.getMessage()));
  7. }
  8. @ExceptionHandler(Exception.class)
  9. public ResponseEntity<Result<String>> handleException(Exception e) {
  10. return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
  11. .body(Result.error(500, "服务器异常"));
  12. }
  13. }

这样就好了,是不是很简单。

 36

啊!这个可能是世界上最丑的留言输入框功能~


当然,也是最丑的留言列表

有疑问发邮件到 : suibibk@qq.com 侵权立删
Copyright : 个人随笔   备案号 : 粤ICP备18099399号-2