JWT
Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).
JWT的组成
JWT由三部分组成:header.payload.signature
header头部
主要包括两部分信息:
- 声明类型(JWT)
- 声明加密算法,通常采用通常直接使用 HMAC SHA256
然后通过base64加密,很显然这是可以直接解密的。
payload载荷
存放有效信息的地方,例如账号信息等
signature签名信息
这个部分由 header 和 payload 经过 base64 编码然后通过header中声明的加密方式进行加盐secret组合加密,然后就构成了jwt的第三部分。secret密钥是存储在服务器中的,可以用来生成token以及验证token是否正确。
JWT的应用
通过JWT绑定用户信息生成Token从而记录登录状态:
- 用户进行登录时,将账号作为公开的信息存入payload中,根据服务器的secret密钥生成Token存储
- 用户进行后续操作时必须在请求头中添加Token,然后服务器根据Token和服务器的secret密钥对signature签名信息进行验证,验证通过则放行。
Java代码实例
引入依赖
1
2
3
4
5
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.3.0</version>
</dependency>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/**
* 生成签名
* @param account 帐号
* @return java.lang.String 返回加密的Token
*/
public static String sign(String account, String currentTimeMillis) {
try {
// 帐号加JWT私钥加密,encryptJWTKey为服务器设置的密钥
String secret = account + Base64ConvertUtil.decode(encryptJWTKey);
// 此处过期时间是以毫秒为单位,所以乘以1000
Date date = new Date(System.currentTimeMillis() + Long.parseLong(accessTokenExpireTime) * 1000);
Algorithm algorithm = Algorithm.HMAC256(secret);
// 附带account帐号信息
return JWT.create()
.withClaim("account", account) //设置payload载荷中的公开账号信息
.withClaim("currentTimeMillis", currentTimeMillis) //设置payload载荷中的时间信息,账号再次登录会生成新的Token,可通过Token创建时间与最新登录时间对比判断Token是否为最新的
.withExpiresAt(date) //设置过期时间
.sign(algorithm); //设置加密算法
} catch (UnsupportedEncodingException e) {
logger.error("JWTToken加密出现UnsupportedEncodingException异常:{}", e.getMessage());
throw new BusinessException(EmBusinessError.UNKNOWN_ERROR,"JWTToken加密出现UnsupportedEncodingException异常:" + e.getMessage());
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
* 获得Token中payload载荷的公开信息
* @param token
* @param claim payload载荷中公开信息的名称
* @return java.lang.String Token中的公开信息
*/
public static String getClaim(String token, String claim) {
try {
DecodedJWT jwt = JWT.decode(token);
// 只能输出String类型,如果是其他类型返回null
return jwt.getClaim(claim).asString();
} catch (JWTDecodeException e) {
logger.error("解密Token中的公共信息出现JWTDecodeException异常:{}", e.getMessage());
throw new BusinessException(EmBusinessError.UNKNOWN_ERROR,"解密Token中的公共信息出现JWTDecodeException异常:" + e.getMessage());
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
* 校验token是否正确
* @param token Token
* @return boolean 是否正确
*/
public static boolean verify(String token) {
try {
// 帐号加JWT私钥解密,encryptJWTKey为服务器设置的密钥
String secret = getClaim(token, Constant.ACCOUNT) + Base64ConvertUtil.decode(encryptJWTKey);
Algorithm algorithm = Algorithm.HMAC256(secret);
JWTVerifier verifier = JWT.require(algorithm).build();
verifier.verify(token);
return true;
} catch (UnsupportedEncodingException e) {
logger.error("JWTToken认证解密出现UnsupportedEncodingException异常:{}", e.getMessage());
throw new BusinessException(EmBusinessError.UNKNOWN_ERROR,"JWTToken认证解密出现UnsupportedEncodingException异常:" + e.getMessage());
} catch (JWTVerificationException e){
logger.error("JWTToken认证解密出现JWTVerificationException异常:{}", e.getMessage());
throw new BusinessException(EmBusinessError.PARAMETER_VALIDATION_ERROR,"JWTToken认证解密出现JWTVerificationException异常:" + e.getMessage());
}
}