浅谈JWT
JWT
JWT就是一个字符串,由header(标头).payload(有效载荷).signature(签名)三部分组成。
用户认证(携带用户名,密码)------服务器验证,生成JWT令牌返回给客户端保存-------客户端每次验证时就携带token去服务器端进行验证
JWT和session相比较就是JWT是加密的形式保存在客户端,这就不会被局限于web形式,不需要在服务器端保存信息,适用于分布式应用。
编码是Base64
#header
{
"alg":"HS256";//所使用的算法
"typ":"JWT";//类型,
}
#Payload //不要放用户敏感信息
{
"sub":""//用户id
"name":""//用户名
"admin": //角色
}
#Signature
header和Payload都是使用Base64编码的,前端可以解码得到里面的信息,然后Signature需要编码以后的header和Payload以及提供的一个密钥,然后使用header中指定的签名算法HS256进行签名。签名的作用就是保证JWT没有被篡改过
生成Token
void setToken() {
Calendar instance = Calendar.getInstance();
instance.add(Calendar.SECOND,200);
HashMap<String, Object> map = new HashMap<>();
String sign = JWT.create().withHeader(map)//默认可以省略
.withClaim("userid", 3)
.withClaim("username", "liyu")
.withExpiresAt(instance.getTime())//指定令牌的过期时间
.sign(Algorithm.HMAC256("asdfadsfdsa"));//指定签名密钥
System.out.println(sign);
}
得到Token,解密拿到信息
void getToken(){
//创建验证对象
JWTVerifier verifier = JWT.require(Algorithm.HMAC256("asdfadsfdsa")).build();
DecodedJWT verify = verifier.verify("这里放生成的Token");
System.out.println(verify.getClaims().get("userid").asInt());
System.out.println(verify.getClaims().get("username").asString());
}
封装为工具类
public static DecodedJWT getInfo(String sign){
DecodedJWT verify = JWT.require(Algorithm.HMAC256(key)).build().verify(sign);
//得到信息
return verify;
}
在这中放入sign的jwt字符串验证时会遇到两次签证不同的异常(SignatureVerificationException)
)
为此写了个check方法
public static boolean check(String token){
JWTVerifier verifier = JWT.require(Algorithm.HMAC256(key)).build();
DecodedJWT info = verifier.verify(token);
if (info!=null){
return true;
}else {
return false;
}
}
验证了依旧是报错,检查生成token函数时才发现是放入的密钥自己加了双引号,所以才导致两次验证的token不一样
String sign = builder.withExpiresAt(instance.getTime()).sign(Algorithm.HMAC256(key));
因为key是已经定义好了的字符串密钥,所以直接放进去就可以了