springboot如何优雅写登陆拦截器

上篇讲了登陆一些基础代码,也说到,没有拦截器的登陆不是完整的登陆,所以这篇讲如何优雅写登陆拦截器

需要两个:拦截器和拦截适配器
其中,
拦截器需要实现HandlerInterceptor,并实现preHandle方法
适配器需要实现WebMvcConfigurer,并实现addInterceptors方法

拦截器通常放在intercepter包下面,拦截适配器通常放在config包下面

首先preHandle方法

入参(实现的时候自动会带):HttpServletRequest、HttpServletResponse、Object
1、从request的header中拿到token
判断:token是否为null或是否为空。如果是,打印出错误码(code)和错误信息(message)。可返回“登陆失效,请重新登陆”------token为空,并返回false
2、解析传入的token,得到后台userid
判断:userid是否为空。如果是,打印出错误码(code)和错误信息(message)。可返回“令牌无效,请重新登录”------token无效:有值但是解析失败,并返回false
3、获取redis中的token
判断:redis中的token是否为null或者redis中的token是否不等于传过来的token,打印出错误码(code)和错误信息(message)。可返回“您已在别处登录”------token过期:解析成功,但是和redis不一致,并返回false
4、返回true

代码在此

public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
     
        String token = request.getHeader("token");
        //判断是否有传token
        if (token == null || "".equals(token)) {
     
            System.out.print("code="+4000+"message=token为空")
            return false;
        }
        //解析传入的token,获得后台user_id
        String userId = JwtToken.getUserId(token);// 这个上篇文章讲过
        if (userId == null) {
     
            System.out.print("code="+4001+"message=token无效:有值但是解析失败")
            return false;
        }
        //获取redis中的token
        String redisTokenKey = String.format(GODZILLA:ADMIN:TOKEN:%s, userId);
        String redisToken = (String) redisTemplate.opsForValue().get(redisTokenKey);
        if (redisToken == null || !redisToken.equals(token)) {
     
            System.out.print("code="+4002+"message=token过期:解析成功,但是和redis不一致")
            return false;
        }
        return true;
    }

然后addInterceptors方法

入参:InterceptorRegistry
1、首先类中生成前台和后台用户的拦截器对象
2、然后重写addInterceptors方法

话不多说,直接上代码

 @Bean
    public AAALoginInterceptor getAAALoginInterceptor() {
      // 这个对应自己的拦截器就ok
        return new AAALoginInterceptor();
    }

    @Bean
    public BBBLoginInterceptor getBBBLoginInterceptor() {
     
        return new BBBLoginInterceptor();
    }
 public void addInterceptors(InterceptorRegistry registry) {
     
        // 前台登录用户拦截器
        registry.addInterceptor(getAAALoginInterceptor()) // 添加拦截器(这个拦截器是getAAALoginInterceptor这个方法的返回,即getAAALoginInterceptor对象)
                .addPathPatterns("/**")// 拦截所有url
                .excludePathPatterns(getCommonExcludePath()) // 除了getCommonExcludePath这个方法中返回的路径
                .excludePathPatterns(getFrontExcludePath());// 除了getFrontExcludePath这个方法中返回的路径

        // 后台登录用户拦截器
        registry.addInterceptor(getBBBLoginInterceptor())
                .addPathPatterns("/**")
                .excludePathPatterns(getCommonExcludePath())
                .excludePathPatterns(getAdminExcludePath());
    }

    /**
     * 统一跳过验证的Path
     * @return
     */
    private List<String> getCommonExcludePath() {
     
        List<String> list = new ArrayList<>();
        list.add("/error");// 以error开头的所有url
        list.add("/swagger-resources/**");//swagger-resources开头的 url
        list.add("/swagger-ui.html/**");// 以swagger-ui.html开头的所有url
        return list;
    }
  private List<String> getBBBExcludePath() {
     
        List<String> list = new ArrayList<>();
        list.add("/aaa/**");// 以aaa开头的所有url
        list.add("/bbb/**"); //以bbbf开头的所有url//todo
        list.add("/bbb/login");// 密码/验证码登录接口 ///bbb/login开头的所有url
        list.add("/bbb/code");// 后台获取验证码 ///bbb/code开头的所有url
        return list;
    }

下面的代码同理

  private List<String> getAAAExcludePath() {
     
        List<String> list = new ArrayList<>();
        list.add("/bbb/**");
        list.add("/aaa/**");
        list.add("/aaa/login");//密码登录接口
        list.add("/aaa/user/verify_code");//验证码登录
        list.add("/aaa/send_vcode");//发送验证码
        return list;
    }

补充一个坑哈
前端在调试登陆接口的时候用token直接登陆,爆出了跨域的错误,后来经排查,我们项目中有用到两个token,一个AAAtoken,一个BBBtoken(我的这个是BBBtoken),跨域只放行了AAAtoken,这时候需要加上BBBtoken才可以

   response.setHeader("Access-Control-Allow-Headers", "Origin,AAAtoken,BBBToken,x-requested-with,Content-Type,Accept");

类似于这样

你可能感兴趣的:(登陆,拦截器,springboot,java,redis,jwt)