什么是token?
token是一种用于身份验证的字符串,由服务器签发,客户端接收token,每次请求都发送token信息,服务器识别token内部数据,保持用户会话的一种技术。
HS256和RS256有什么区别?
RS256 (采用SHA-256 的 RSA 签名) 是一种非对称算法, 它使用公共/私钥对: 标识提供方采用私钥生成签名, JWT 的使用方获取公钥以验证签名。由于公钥 (与私钥相比) 不需要保护, 因此大多数标识提供方使其易于使用方获取和使用 (通常通过一个元数据URL)。
另一方面, HS256 (带有 SHA-256 的 HMAC 是一种对称算法, 双方之间仅共享一个 密钥。由于使用相同的密钥生成签名和验证签名, 因此必须注意确保密钥不被泄密。
JWT结构
三部分
header.payload.signture
header
header包括2部分内容,一个是token类型(JWT)和使用加密算法类型(HS256 or RS256),设置好内容之后,JWT会使用Base64对头部信息进行编码,生产一串字符串。例:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
{
"typ": "JWT",
"alg": "HS256"
}
String header = "{\"typ\"=\"JWT\",\"alg\"=\"HS256\"}";
System.out.printf("header"+header);
// base64加密
String a = Base64.getEncoder().encodeToString(header.getBytes());
System.out.printf("a"+a);
// base64解密
byte[] b = Base64.getDecoder().decode(a);
String b1 = new String(b);
System.out.printf("b1"+b1);
//eyJ0eXAiPSJKV1QiLCJhbGciPSJIUzI1NiJ9b1
payload
payload(荷载)用来存放Token的具体信息,可以是自定义的信息或是标准字段,由JWT预定义.
公共的声明
私有的声明
标准中注册的声明
以下为标准字段:
iss:Issuer,Token签发者
sub:Subject,Jwt面向的用户
aud:Audience,jwt接收一方
exp:Expiration time,Token过期时间
nbf:Not before 定义某时间前,Token不可用
iat:Issued at,token发行时间
jti:JWT ID token身份标识,用来避免重复重放攻击
signature
这是一个签证信息,由三部分组成:
header的base64编码后
payload的base64后
secret
这个部分由以上header和payload部分使用.连接后,通过header头部定义的加密算法进行加盐secret组合加密。
演示代码
maven
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.0</version>
</dependency>
public class utils {
// 私钥
private static final String SECRET_KEY = "this is a secret key";
public static void main(String[] args) {
// 生成token
String jwtToken = Jwts.builder()
// 头部
.setHeaderParam("typ", "JWT")
// jwt 标注中的申明
.setIssuedAt(new Date()) // 签发时间
.setExpiration(new Date(new Date().getTime() + 10000L))// 过期时间
.setSubject("19930311")// jwt面向的客户
.setIssuer("huan")// jwt的签发者
// 公共申明和私有申明
.claim("user_id", "admin")
.claim("user_name","liwei")
.claim("user_pwd","123456")
// 签证
.signWith(SignatureAlgorithm.HS256, SECRET_KEY.getBytes())
.compact();
System.out.println("生成的 jwt token 如下:" + jwtToken);
// 验证jwt
Jws<Claims> claimsJws = Jwts.parser()
// 验证签发者字段iss 必须是 huan
.require("iss", "huan")
// 设置私钥
.setSigningKey(SECRET_KEY.getBytes())
// 解析jwt字符串
.parseClaimsJws(jwtToken);
// 获取头部信息
JwsHeader header = claimsJws.getHeader();
// 获取载荷信息
Claims payload = claimsJws.getBody();
System.out.println("解析过来的jwt的header如下:" + header.toString());
System.out.println("解析过来的jwt的payload如下:" + payload.toString());
}
}