JWT使用教程
# JWT规范
JSON WEB TOKEN是支持跨域的认证解决方案。解决了 Cookie-Session 方案不支持跨域、拓展性不好的问题。
# 1、 jwt认证流程
- 客户端发送认证信息到服务端,认证成功返回 Token
- 客户端收到 Token 之后,可以存放在 Cookie 或者 localStorage中,每次请求放在请求头Authorization中:
Authorization: Bearer <token>
1
# 2、token的组成
JWT 内容由三部分组成,分别是头部(Header)、负载(Payload)、签名(Signature)。中间用
.
连接。大概就是下面这样:
Header.Payload.Signature
1
# Header部分
Header部分是一个JSON对象,描述JWT元数据。下例:
{
"alg": "HS256",
"typ": "JWT"
}
1
2
3
4
2
3
4
其中, alg
是签名算法, typ
表示令牌的类型。这部分数据会通过 Base64URL 编码到 Token 放到 token 头部。
# Payload部分
Payload部分也是一个JSON对象,存放实际需要传输的数据,这部分是不加密的。JWT规范定义了7个字段,供选用。
- iss (issuer):签发人
- exp (expiration time):过期时间
- sub (subject):主题
- aud (audience):受众
- nbf (Not Before):生效时间
- iat (Issued At):签发时间
- jti (JWT ID):编号
也可以定义额外的字段。这部分信息也会通过 Base64URL 编码之后拼接到 Token 中。
# Signature部分
Signature是对Header和Payload的签名,防止数据被篡改。保证前面身份信息的数据一定是服务器签发的而不是客户端杜撰的。
首先需要一个秘钥(secret)。这个秘钥存在服务器端,用户不可以知道。然后使用 Header 里面指定的签名算法(默认 HMAC SHA256),按照下面公式生成:
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
1
2
3
4
2
3
4
算出结果后,拼接在 Token 尾部返回给客户端。
# auth0.jwt使用
com.oauth.jwt
是 Java的一个JWT规范实现。
# 1、引入依赖
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.3.0</version>
</dependency>
1
2
3
4
5
2
3
4
5
# 2、生成 token
String token = JWT.create()
.withJWTId("编号")
.withIssuer("签发人")
.withExpiresAt(new Date()) // 过期时间
.withSubject("主题")
.withAudience("受众")
.withNotBefore(new Date()) //生效时间
.withIssuedAt(new Date()) // 签发时间
.withClaim("key", "value")
.sign(Algorithm.HMAC256("秘钥"));
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
# 3、从Token中读取信息
DecodedJWT decode = JWT.decode();
String header = decode.getHeader();
String payload = decode.getPayload();
String signature = decode.getSignature();
String id = decode.getId();
String issuer = decode.getIssuer();
Date expiresAt = decode.getExpiresAt();
String subject = decode.getSubject();
List<String> audience = decode.getAudience();
Date notBefore = decode.getNotBefore();
Date issuedAt = decode.getIssuedAt();
String value = decode.getClaim("key").asString();
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
# 4、 验证Token是否被篡改
JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256("秘钥")).build();
try {
jwtVerifier.verify(token);
}catch (JWTVerificationException e) {
throw new RuntimeException("401");
}
1
2
3
4
5
6
2
3
4
5
6
# 5、后续
如果Token验证通过,那么 Payload 中的信息就是可信任的。
参考链接:
- https://www.ruanyifeng.com/blog/2018/07/json_web_token-tutorial.html
- https://github.com/auth0/java-jwt/blob/master/EXAMPLES.md