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);
}
}
详细解析:
-
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
:这是doFilter
方法的定义,它接收三个参数:ServletRequest
对象、ServletResponse
对象和FilterChain
对象。这个方法在过滤器被调用时执行,用于处理请求和响应。 -
HttpServletRequest req = (HttpServletRequest) request;
:将传入的ServletRequest
对象强制转换为HttpServletRequest
对象,以便使用HTTP特定的方法。 -
HttpServletResponse resp = (HttpServletResponse) response;
:将传入的ServletResponse
对象强制转换为HttpServletResponse
对象,以便使用HTTP特定的方法。 -
String url = req.getRequestURL().toString();
:获取请求的URL,并将其转换为字符串。 -
String url = req.getRequestURL().toString();
:获取请求的URL,并将其转换为字符串。 -
if (url.contains("login")) {
:检查URL是否包含"login"字符串。如果包含,说明这是一个登录操作。 -
String jwt = req.getHeader("token");
:从请求头中获取名为"token"的值,并将其存储在变量jwt
中。 -
if (!StringUtils.hasLength(jwt)) {
:检查jwt
变量是否为空或长度为0。如果为空或长度为0,说明没有提供令牌。 -
String notLogin = JSONObject.toJSONString(error);
:将error
对象转换为JSON字符串。 -
JwtUtils.parseJWT(jwt);
:尝试解析提供的令牌。如果解析失败,将抛出异常。 -
String notLogin = JSONObject.toJSONString(error);
:将error
对象转换为JSON字符串。 -
resp.getWriter().write(notLogin);
:将未登录的错误信息写入响应的输出流。