JWT解释
JWT是一种加密后的数据载体,可在各应用间进行数据传输。
JWT的组成
包含3部分。header(头)、payload(有效载荷)、signature(签名)。格式是header.payload.signature
Header
组成
JWT的头部承载两部分信息
声明类型,默认是JWT
声明加密的算法 常用的算法:HMAC、RSA、ECDSA等
bash
{
"alg":"HS256"
"typ":"JWT"
}
alg:表示签名的算法,默认是 HMAC SHA256(写成 HS256);
typ:表示令牌(token)的类型,JWT 令牌统一写为 JwT。使用Base64加密,构成了JT第一部分-header
Payload
组成
Payload 部分也是一个JSON 对象,用来存放实际需要传递的有效信息。
标准载荷:有很多,建议使用,但不强制,对T信息作补充。
标准载荷 | 介绍 |
---|---|
iss (issuer) | 签发人(谁签发的) |
exp (expiration time) | 过期时间,必须要大于签发时间 |
sub (subject) | 主题(用来做什么) |
aud (audience) | 受众(给谁用的)比如:http://www.xxx.com |
nbf (Not Before) | 生效时间 |
iat (lssued At) | 签发时间 |
jti (JWT ID) | 编号,JWT的唯一身份标识 |
自定义载荷:可以添加任何的信息,一般添加用户的相关信息或其他业务需要的必要信息。但不建议添加敏感信息,因为该部分在客户端可解密。
bash
{
#自定义载荷
"user_info":[
{"id": "1"},
{"name": "lili"},
{"age": "18"}
]
#标准载荷
"iat": 1681571257.
"exp":1682783999
"aud":"xiaofei",
"iss":"dafei"
"sub": "alluser'
}
使用Base64加密,构成了JT第二部分payload
signature
组成
Signature 部分是对前两部分的签名,防止数据篡改。
首先,需要指定一个密钥(secret)。这个密钥只有服务器才知道,不能泄露给用户。然后,使用 Header 里面指定的签名算法(默认是 HMAC SHA256),按照下面的公式产生签名。
java
signature =HMACSHA256(base64urlEncode(header)+""+ base64UrlEncode(payload),secret)
算出签名以后,把 Header、Pavload、signature 三个部分拼成一个字符串,每个部分之间用"点"(.)分隔,就可以返回给用户。
因为有这个密钥的存在,所以即便调用方偷偷的修改了前两部分的内容,在验证环节就会出现签名不一致的情况,所以保证了安全性。
使用Base64加密,构成了JT第三部分-signature
实践
xml
<dependencies>
<!--JWT(Json Web Token)登录支持-->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.11.5</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.11.5</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.11.5</version>
<scope>runtime</scope>
</dependency>
</dependencies>
java
public class JwtUtil {
static String USER_INFO_USERNAME = "username";
static int JWT_EXPIRATION = 24 * 60 * 60 * 1000;
static String JWT_SECRET = "jwtsecretfdghfghfdfgdfgdfsgdfgdfgfdgdfgdfgdfgdfg";
static String JWT_CREATE_TIME = "jwtCreateTime";
static String USER_INFO_ID = "id";
public static String createToken(Map<String, Object> claims) {
String token = Jwts.builder()
// .setHeader(new HashMap<>())
.setAudience("Audience")
.setIssuer("Issuer")
.setSubject("Subject")
.setNotBefore(new Date())
.setIssuedAt(new Date())
.setId("jwt id")
.setClaims(claims)//载荷
.setExpiration(generateExpirationDate())
.signWith(Keys.hmacShaKeyFor(Decoders.BASE64.decode(JWT_SECRET)))
.compact();
return token;
}
private static Date generateExpirationDate() {
return new Date(System.currentTimeMillis() + JWT_EXPIRATION);
}
public static Claims parseToken(String token) {
Claims claims = Jwts.parserBuilder()
.setSigningKey(Decoders.BASE64.decode(JWT_SECRET))
.build()
.parseClaimsJws(token)
.getBody();
return claims;
}
public static String getUsername(String token) {
Claims claims = parseToken(token);
return getValue(claims, USER_INFO_USERNAME);
}
public static boolean validateToken(String token) {
Claims claims = parseToken(token);
return claims != null && !isTokenExpired(token);
}
private static boolean isTokenExpired(String token) {
Date expiredDate = getExpiredDate(token);
return expiredDate.before(new Date());
}
private static Date getExpiredDate(String token) {
Claims claims = parseToken(token);
return claims.getExpiration();
}
private static String refreshToken(String token) {
Claims claims = parseToken(token);
claims.put(JWT_CREATE_TIME, new Date());
return createToken(claims);
}
private static String getValue(Claims claims, String key) {
return claims.get(key) != null ? claims.get(key).toString() : null;
}
}
java
@RestController
public class UserController {
private static Map<String, User> map = new HashMap();
@GetMapping("/register")
public String register(User user) {
Map<String, Object> claims = new HashMap<>();
claims.put(USER_INFO_ID, user.getId());
claims.put(USER_INFO_USERNAME, user.getUsername());
claims.put(JWT_CREATE_TIME, new Date());
String token = JwtUtil.createToken(claims);
map.put(token, user);
return "/active?jwt= " + token;
}
public void active(String jwt) {
User user = map.get(jwt);
if (user != null && JwtUtil.validateToken(jwt)) {
map.remove(jwt);
System.out.println("active");
} else {
System.out.println("param 不合法 ");
}
}
}