一、JWT介绍。
1. 什么是JWT。
JWT
全称JSON WEB TOKEN
,是一种基于JSON的用于认证的令牌。
2. JWT的组成。
头信息(header
),消息体(负载 payload
)和签名(signature
)。它们之间用点儿分隔。
2.1. 头信息。
头信息通常包含两部分,type
:代表token的类型,这里使用jwt。alt
:使用的Hash算法,如:HMAC-SHA256
{
"alg":"HS256",
"typ":"JWT"
}
2.2. 负载。
它包含一些声明Claim,是一些用户的状态和元数据,Claim分三种类型
1)reserved
。
是官方预定义好的,JWT不会强制你去使用,但是建议你去使用。
常用的有 iss(签发者),exp(过期时间戳), sub(面向的用户), aud(接收方), iat(签发时间)
2)public
和 private
。
这里都是用户自己定义的字段。不建议保存私密信息。
{
"username":"lisi",
"role":"admin"
}
2.3. 签名
用头信息和消息体生成的,生成规则如下:
key=”secre_tkey” ; // 自己指定 私有的key
unsignedToken = encodeBase64(header)+ ‘.’ + encodeBase64(payload);
signatrue = HMAC-SHA256(key,unsignedToken);
2.4. 最终
token = encodeBase64(header) + ‘. ’ + encodeBase64(payload) + ‘. ’ +
encodeBase64(signature);
dfad最终的token
的样子:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
.
eyJsb2dnZWRJbkFzIjoiYWRtaW4iLCJpYXQiOjE0MjI3Nzk2Mzh9.
gzSraSYS8EXBxLN_oWnFSRgCzcmJmMjLiuyu5CSpyHI
3. JWT流程图示
二、Demo演示
public class JWTUtils {
private static final String SECRET = "huitiankeji";// 公用密钥--汇天科技
/**
* 生成token
* @param user 对象
* @param maxAge 最大生存时间
* @return 令牌
*/
public static String createToken (User user, long maxAge) throws Exception{
// 设置header
Map<String ,Object> headers =new HashMap<String ,Object>();
headers.put("alg","HS256"); //加密算法
headers.put("typ","JWT");
// 生成token 头信息 设置过期时间 签名时间 将用户信息设置json
String token = JWT.create()
.withHeader(headers)
.withExpiresAt(new Date(System.currentTimeMillis() + maxAge))
.withIssuedAt(new Date())
.withClaim("user", new ObjectMapper().writeValueAsString(user))
.sign(Algorithm.HMAC256(SECRET));
return token;
}
/**
* 解析令牌成为对象
* @param token 传入令牌
* @return // 返回对象
* @throws Exception
*/
public static User verifyToken(String token) throws Exception{
// 创建解析器,用来将String的令牌解析成jwt对象
JWTVerifier verifier = JWT.require(Algorithm.HMAC256(SECRET)).build();
// 解析
DecodedJWT jwt = verifier.verify(token);
// 从对象中拿出来user的键值对
Claim userClaim = jwt.getClaim("user");
String json = userClaim.asString();
// 用jackson将String转换成对象
User user = new ObjectMapper().readValue(json, User.class);
return user;
}
}
测试:
public class TestUtils {
public static void main(String[] args) throws Exception {
// 测试获取
// User user = new User(1, "zhangsan", "123456", "张三!");
// String token = JWTUtils.createToken(user, 30L * 24L * 3600L * 1000L);
// System.out.println(token);
// 测试解析
User user = JWTUtils.verifyToken("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1MzI2ODUyMTYsImlhdCI6MTUzMDA5MzIxNiwidXNlciI6IntcImlkXCI6MSxcInVzZXJuYW1lXCI6XCJ6aGFuZ3NhblwiLFwicGFzc3dvcmRcIjpcIjEyMzQ1NlwiLFwibmFtZVwiOlwi5byg5LiJXCJ9In0._56THpD6T-epjkLcqJBG7hJqaY4vQ7NtU7E5QiuPB8s");
System.out.println(user);
}
}
三、应用场景。
dfdfdf身份认证在这种场景下,一旦用户完成了登陆,在接下来的每个请求中包含JWT,可以用来验证用户身份以及对路由,服务和资源的访问权限进行验证。由于它的开销非常小,可以轻松的在不同域名的系统中传递,所有目前在单点登录(SSO)中比较广泛的使用了该技术。信息交换在通信的双方之间使用JWT对数据进行编码是一种非常安全的方式,由于它的信息是经过签名的,可以确保发送者发送的信息是没有经过伪造的。