什么是JWT
jwt 简介 json web token ,简要说明:前端传验证信息到后端,后端验证通过,返回一个对象,只不过这个对象是被加密的,这样后端就可以为无状态的,每次请求的时候,请求头带上token ,里面封装了对象的信息,我们只需要用拦截器进行拦截,解析token,后端就可以知道是谁登录了界面,可以设置相应的超时时间,超时时间不应太长或者太短,根据实际情况而定,超时用户就需要从新登录
优点: 减少服务器的压力,不用向以前一样将对象保存在session里面,或者是利用redis保存信息,因为redis也是要占用服务器的内存的。非常适合springcloud 微服务。
官网:https://jwt.io/libraries
jwt的组成
-
头部 Header
{ "alg":"HS256", "typ":"JWT" }
-
Payload 负载
也是一个json 的对象,下面是官方字段:
iss (issuer):签发人 exp (expiration time):过期时间 sub (subject):主题 aud (audience):受众 nbf (Not Before):生效时间 iat (Issued At):签发时间 jti (JWT ID):编号
也可以定义一些其他的字段
{ "userId":12, "userName":"DIANWEI" }
由于jwt 默认是不加密的,所以不要保存敏感信息
-
Signature
Signature部分是对前两部分的签名,防止数据篡改。
首先,需要指定一个密匙(secret)。这个密钥只有服务器才知道,不能泄露给用户。然后,使用 Header 里面指定的签名算法(默认是 HMAC SHA256),按照下面的公式产生签名。
算出签名以后,把 Header、Payload、Signature 三个部分拼成一个字符串,每个部分之间用"点"(.)分隔,就可以返回给用户。
官网提供了六种实现方式:
jjwt:
java-jwt:
这里附上我们正在使用的jjwt代码:
String key = "22222";
@Test
public void testGenerateToken() {
//过期时间
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.SECOND, 60);
//创建payload 的私有声明(根据特定的业务需要添加)
Map<String, Object> claims = new HashMap<>();
claims.put("userId", 123);
claims.put("userName", "典韦");
claims.put("url", "http://");
JwtBuilder builder = Jwts.builder()
.setClaims(claims)
.setExpiration(calendar.getTime())
//设置签名使用的签名算法和签名使用的密匙
.signWith(SignatureAlgorithm.HS256, key);
String compact = builder.compact();
System.out.println(compact);
}
@Test
public void testVerify() {
String token = "eyJhbGciOiJIUzI1NiJ9.eyJ1c2VyTmFtZSI6IuWFuOmfpiIsImV4cCI6MTY0NzA2NjcyMiwidXNlcklkIjoxMjMsInVybCI6Imh0dHA6Ly8ifQ.9eYciqHwha6pnwRDVRlmPOXrvE9n123FMvgda3t0waA";
try {
Claims claims = Jwts.parser() //得到DefaultJwtparser
.setSigningKey(key) //设置签名用到的key
.parseClaimsJws(token).getBody(); //设置需要解析的jwt
Integer userId = claims.get("userId", Integer.class);
String userName = claims.get("userName", String.class);
String url = claims.get("url", String.class);
System.out.println("userId:" + userId);
System.out.println("userName:" + userName);
System.out.println("url:" + url);
} catch (ExpiredJwtException e) {
e.printStackTrace();
System.out.println("令牌已过期");
} catch (UnsupportedJwtException e) {
e.printStackTrace();
System.out.println("签名不支持");
} catch (MalformedJwtException e) {
e.printStackTrace();
System.out.println("签名格式错误");
} catch (SignatureException e) {
e.printStackTrace();
System.out.println("签名不一致");
} catch (IllegalArgumentException e) {
e.printStackTrace();
System.out.println("参数不正确");
} catch (Exception e) {
e.printStackTrace();
System.out.println("校验失败");
}
}