拦截器 + token的登录验证

403 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第32天,点击查看活动详情

拦截器 + token的登录验证

相信各位有进行过系统开发经验的朋友们,肯定会了解一个系统最基础的功能,那就是实现用户登录,而这个用户登录是需要经过认证的,只要通过了认证才会让用户访问其他重要页面的,就好像在某个系统中,你不登录和登录所能执行的操作是不一样的。

今天我们就一起来聊聊这个话题,话不多说,我们马上出发!

基于jwt的token认证

token就相当于一个令牌一样,用户第一次登录的时候,后端系统需要生成一个独一无二的token返回给前端,以后的每次访问前端都会自动带上这个token,这样就区分开了,登录状态和未登录状态。

一般未登录状态在访问时,系统会自动重定向到登录页面,给用户登录。

下面给出一种生成token的实现方式:

    //生成token字符串
    public static String createToken(Long userId, String userName, String email) {
        String token = Jwts.builder()
​
                .setSubject("YYGH-USER")
​
                .setExpiration(new Date(System.currentTimeMillis() + tokenExpiration))
​
                .claim("id", userId)
                .claim("email", email)
                .claim("userName", userName)
​
                .signWith(SignatureAlgorithm.HS512, tokenSignKey)
                .compressWith(CompressionCodecs.GZIP)
                .compact();
        return token;
    }
​

这个token是根据用户id、用户名、用户邮箱的基本信息来生成的,保证了token和用户的一一对应。

拦截器-拦截请求

下面给出一种拦截器的实现,是通过重写 HandlerInterceptor 中的 preHandle方法来实现的。

具体流程如下:

  1. 判断到来的请求是否携带了 token,如果没携带,则响应信息并拦截
  2. 如果到来的请求携带了 token,则在redis中查是否存在对应的token,如果存在,则放行,否则拦截
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        response.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charset=utf-8");
​
        String token = request.getHeader("token");
        if (StringUtils.isEmpty(token)) {
            response.getWriter().print("用户未登录,快去登录吧,快去!");
            return false;
        }
        Object loginStatus = redisTemplate.opsForValue().get(token);
        System.out.println("拦截器,去查redis啦。。。");
        if( Objects.isNull(loginStatus)){
            response.getWriter().print("token错误,快去检查!");
            return false;
        }
        return true;
    }
​

而上面这个拦截器究竟是拦截什么请求呢?

是所有请求都拦截吗?还是可以设置的呢?

其实是可以设置的。

拦截器的路径配置:

拦截器的配置是通过重写WebMvcConfigurer 中的方法来实现的,下面给出了一个重写addIntercepter方法的实现。

    /**
     * 拦截
     * @param registry
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        String[] addPathPatterns ={
                //输入要拦截路径
                //拦截所有路径 ,之后再决定放行
                "/**"
        };
        //设置排除放行路径
        //要排除路径,排除的路径可以直接放行
        String[] excludePathPatterns={
                "/system/login",  //排除掉登录请求
        };
        registry.addInterceptor(initAuthInterceptor())
                .addPathPatterns(addPathPatterns)
                .excludePathPatterns(excludePathPatterns);
    }
​