0%

jwt

文章字数:583,阅读全文大约需要2分钟

jwt介绍

传统用户登录后会使用session存储用户信息,session依靠cookie来记录sessionId,而移动端没有cookie
jwt本质上是一串字符串,包含头部、内容、签名三部分。头部可以存储加密方式等信息,内容可以是用户基本信息,签名是对前面两部分的签名,用来验证真伪。使用jwt后服务端无需保存用户状态,每次用户请求都需要带上jwt的字符串,以此表明身份。不依赖session的存储用户信息,更适合分布式及移动端

jwt结构

1
2
# base64的头部 + "." + base64的内容 + "." + 对于前面部分的签名
base64(headerJson).base64(payload).HMACSHA256(base64UrlEncode(header)+"."+base64UrlEncode(payload),secret);

Header

一般存储以下内容

1
2
3
4
{
"alg": "HS256",
"typ": "JWT"
}

payload

payload只经过base64,是可逆的,相当于明文。所以最好不要放置敏感信息

1
2
3
4
5
6
7
8
9
10
11
12
13
# 标准的jwt主体可以使用这七个默认字段
iss:发行人
exp:到期时间
sub:主题
aud:用户
nbf:在此之前不可用
iat:发布时间
jti:JWT ID用于标识该JWT
# 也可以自己定义
{
"name": "123",
"token": "zzzzdasd"
}

Signature

1
HMACSHA256(base64UrlEncode(header)+"."+base64UrlEncode(payload),secret)

签名算法主要有

  1. HMAC哈希消息验证码对称算法:HS256/HS384/HS512
  2. RSASSA非对称的RSA签名算法:RS256/RS384/RS512
  3. ECDSA非对称的椭圆曲线数据签名算法: ES256/ES384/ES512

java中使用

  • java-jwt
1
2
3
4
5
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.10.3</version>
</dependency>
  • 生成jwt

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    // 指定token过期时间为10天
    Calendar calendar = Calendar.getInstance();
    calendar.add(Calendar.DATE, 10);
    // 生成
    String token = JWT.create()
    .withHeader(new HashMap())// header的内容
    .withClaim("key1", "value")// payload
    .withClaim("key2", "value")
    .withExpiresAt(calender.getTime())// 过期时间
    .sign(Algorithm.HMA256("pwd"));
  • 校验及获取内容

1
2
3
4
5
6
7
// 解析对象
JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256("pwd")).build();
// 校验及解析
DecodedJWT decodedJWT = jwtVerifier.verify(token);
// 之后就能获取其中的内容
Claim userId = decodedJWT.getClaim("key1");
Claim userName = decodedJWT.getClaim("key2");
  • 非对称加密签名
1
2
3
4
RSA rsa = new RSA("pwd", null);
RSAPrivateKey privateKey = (RSAPrivateKey) rsa.getPrivateKey();
// 然后传入签名
JWT.create().withClaim("k","v").sign(Algorithm.RSA256(null, privateKey));
  • 校验时
1
2
3
4
RSA rsa = new RSA(null, "pwd");
RSAPublicKey publicKey = (RSAPublicKey) rsa.getPublicKey();
JWTVerifier jwtVerifier = JWT.require(Algorithm.RSA256(publicKey, null)).build();
DecodedJWT decodedJWT = jwtVerifier.verify(token);