JWT令牌的获取与过滤器Filter的使用

JWT,全称JSON Web Token(JSON Web令牌),是一个开放标准 (rfc7519)。它定义了一种紧凑的、自包含的方式,以JSON对象的形式安全地在各方之间传输信息。这种信息可以被验证和信任,因为它是通过数字签名实现的。

JWT可以使用HMAC算法或使用RSA的公钥/私钥对进行签名,防止被篡改。JWT基于json,非常方便解析,可以在令牌中自定义丰富的内容,易扩展。通过非对称加密算法及数字签名技术,JWT防止篡改,安

全性高。

    //生成JWT
    @Test
    public void testGenJwt(){
        Map<String,Object> claims = new HashMap<>();
        claims.put("id", 1);
        claims.put("name", "tom");

        String jwt = Jwts.builder()
                .signWith(SignatureAlgorithm.HS256, "monian") //签名算法
                .setClaims(claims) //自定义内容(载荷)
                .setExpiration(new Date(System.currentTimeMillis() + 3600 * 1000)) //设置有效期为1h
                .compact();
        System.out.println(jwt);
    }

    //解析令牌
    @Test
    public void testParseJwt(){
        Claims claims = Jwts.parser()
                .setSigningKey("monian")
                .parseClaimsJws("eyJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoidG9tIiwiaWQiOjEsImV4cCI6MTcwMTUxMTAwMH0.3ejLF6AimqpzbmTmN6WPcJvxoXAFPT9c5oNbk-0U5o4")
                .getBody();
        System.out.println(claims);
    }
}

 控制台:

eyJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoidG9tIiwiaWQiOjEsImV4cCI6MTcwMTY2Mzc0NX0.HGgjyiW398CeKGosnOXGxd68KF3nJ_R8LYRrkG8-Ih8

 在JWT官网解析可得:

通过测试类解析令牌可得: 

Demo测试:通过JWT令牌判断用户是否登录,否则不能访问相关的数据: 

@Slf4j
@WebFilter(urlPatterns = "/*")
public class LoginCheckFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {

        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse resp = (HttpServletResponse) response;

        //1.获取请求url
        String url = req.getRequestURL().toString();
        log.info("请求的url:{}", url);

        //2.判断请求url是否包含login,如果包含说明是登陆操作,放行
        if (url.contains("login")) {
            log.info("登陆操作,放行...");
            chain.doFilter(request, response);
            return;
        }

        //3.获取请求头中的令牌(token)
        String jwt = req.getHeader("token");

        //4.判断令牌是否存在,如果不存在,返回错误结果(未登录)
        if (!StringUtils.hasLength(jwt)) {
            log.info("请求头token为空,返回未登录的信息");
            Result error = Result.error("NOT_LOGIN");
            //手动转化 对象——json ----> 阿里巴巴fast.JSON
            String notLogin = JSONObject.toJSONString(error);
            resp.getWriter().write(notLogin);
            return;
        }

        //5.解析token,如果解析失败,返回错误结果(未登录)
        try {
            JwtUtils.parseJWT(jwt);
        } catch (Exception e) {
            e.printStackTrace();
            log.info("解析令牌失败,返回未登录错误信息");
            Result error = Result.error("NOT_LOGIN");
            //手动转化 对象-- json --------> 阿里巴巴fastJSON
            String notLogin = JSONObject.toJSONString(error);
            resp.getWriter().write(notLogin);
            return;
        }


        //6.放行
        log.info("令牌合法,放行");
        chain.doFilter(request, response);
    }
}

详细解析: 

  1. public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException:这是doFilter方法的定义,它接收三个参数:ServletRequest对象、ServletResponse对象和FilterChain对象。这个方法在过滤器被调用时执行,用于处理请求和响应。

  2. HttpServletRequest req = (HttpServletRequest) request;:将传入的ServletRequest对象强制转换为HttpServletRequest对象,以便使用HTTP特定的方法。

  3. HttpServletResponse resp = (HttpServletResponse) response;:将传入的ServletResponse对象强制转换为HttpServletResponse对象,以便使用HTTP特定的方法。

  4. String url = req.getRequestURL().toString();:获取请求的URL,并将其转换为字符串。

  5. String url = req.getRequestURL().toString();:获取请求的URL,并将其转换为字符串。

  6. if (url.contains("login")) {:检查URL是否包含"login"字符串。如果包含,说明这是一个登录操作。

  7. String jwt = req.getHeader("token");:从请求头中获取名为"token"的值,并将其存储在变量jwt中。

  8. if (!StringUtils.hasLength(jwt)) {:检查jwt变量是否为空或长度为0。如果为空或长度为0,说明没有提供令牌。

  9. String notLogin = JSONObject.toJSONString(error);:将error对象转换为JSON字符串。

  10. JwtUtils.parseJWT(jwt);:尝试解析提供的令牌。如果解析失败,将抛出异常。

  11. String notLogin = JSONObject.toJSONString(error);:将error对象转换为JSON字符串。

  12. resp.getWriter().write(notLogin);:将未登录的错误信息写入响应的输出流。