springboot使用拦截器实现登录拦截

发布时间 2023-11-20 12:04:05作者: yaya_sama

参考文档

https://blog.csdn.net/qq_50652600/article/details/127250413

HandlerInterceptor

作用:自定义拦截器

如何创建:这个接口我们通常会自定义一个类。加上@Component注解,并且使它实现HandlerInterceptor接口(根据需求重写里面的三个方法)

public interface HandlerInterceptor {
    default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        return true;
    }

    default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
    }

    default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
    }
}
  1. preHandle:此方法的作用是在请求进入到Controller进行拦截,有返回值。(返回true则将请求放行进入Controller控制层,false则请求结束返回错误信息)
    • 用法:登录验证(判断用户是否登录)权限验证:判断用户是否有权访问资源(校验token)
  2. postHandle:该方法是在Controller控制器执行完成但是还没有返回模板进行渲染拦截。没有返回值。就是Controller----->拦截------>ModelAndView。
    • 用法:因此我们可以将Controller层返回来的参数进行一些修改,它就包含在ModelAndView中,所以该方法多了一个ModelAndView参数。
  3. afterCompletion:该方法是在ModelAndView返回给前端渲染后执行。
    • 用法:例如登录的时候,我们经常把用户信息放到ThreadLocal中,为了防止内存泄漏,就需要将其remove掉,该操作就是在这里执行的。

使用方法

1、创建自定义拦截器,实现HandlerInterceptor接口,这里以登陆拦截器为例

/**
 * @Author:tzl
 * @Date:2023/11/20 11:24
 */
@Slf4j
public class UserLoginInterceptor implements HandlerInterceptor {

    private RedisTemplate redisTemplate;

    public UserLoginInterceptor(RedisTemplate redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // .... 添加你的操作
        this.initUserLoginVo(request);
        return true;
    }

    private void initUserLoginVo(HttpServletRequest request) {
        // 1、从请求头获取到token
        String token = request.getHeader("token");
        log.info("token:{}", token);
        // 2、取出token中的userId
        if (StringUtils.isNotBlank(token)) {
            Long userId = JwtHelper.getUserId(token);
            // 3、通过userId从redis中取出user
            UserLoginVo userLoginVo = (UserLoginVo) redisTemplate.opsForValue().get(RedisConst.USER_LOGIN_KEY_PREFIX + userId);
            if (userLoginVo != null) {
                // 4、将值都存入ThreadLocal中
                AuthContextHolder.setUserId(userLoginVo.getUserId());
                AuthContextHolder.setWareId(userLoginVo.getWareId());
                AuthContextHolder.setUserLoginVo(userLoginVo);
            }
        }
    }

}

2、 将自定义拦截器加入到配置中,配置需要继承WebMvcConfigurationSupport

/**
 * @Author:tzl
 * @Date:2023/11/20 11:43
 */
@Configuration
public class LoginMvcConfigurerAdapter extends WebMvcConfigurationSupport {

    @Resource
    private RedisTemplate redisTemplate;

    @Override
    protected void addInterceptors(InterceptorRegistry registry) {
        // 添加自定义拦截器,设置路径
        registry.addInterceptor(new UserLoginInterceptor(redisTemplate))
                // 拦截小程序请求
                .addPathPatterns("/api/**")
                // 排除登陆请求
                .excludePathPatterns("/api/user/weixin/wxLogin/*");
        super.addInterceptors(registry);
    }
}