文章字数: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);
|
一般存储以下内容
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)
|
签名算法主要有
HMAC
哈希消息验证码对称算法:HS256/HS384/HS512
RSASSA
非对称的RSA
签名算法:RS256/RS384/RS512
ECDSA
非对称的椭圆曲线数据签名算法: ES256/ES384/ES512
java中使用
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
| Calendar calendar = Calendar.getInstance(); calendar.add(Calendar.DATE, 10);
String token = JWT.create() .withHeader(new HashMap()) .withClaim("key1", "value") .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);
|