Token认证实现

JWT Token认证实现

简单说明

JWT Token是Token Auth认证的一种实现方式,当用户将用户名和密码发送到服务器认证且认证通过后,服务器会将认证后的一些信息 例如:认证过期时间、用户名、用户的访问权限等,将这些信息加密成一个字符串(即token)后返回给客户端,返回的形式可以是Cookie形式也可以是json格式返回。每次用户请求新页面时只需把该字符串携带上即可。

JWT Token在加密认证后的信息时,会使用加密算法+密钥的形式生成一个token字符串,token字符串上有一段加密后的签名字符串,用户请求资源时 服务端会先使用密钥验证token的签名字符串,由于密钥是服务器上私有的,只有服务器自己知道,所以确保了验证的安全性,当使用密钥验证签名失败时,则认证该用户认证失败

JWT token的组成和生成过程

一个JWT token字符串由三部分组成:头部(header)、载荷(payload)、签名(signature)

形成一个JWT token字符串的步骤,sign()是生成token的方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
private String sign() throws SignatureGenerationException {
//1.使用Base64加密头部(header)信息形成字符串
String header = Base64.encodeBase64URLSafeString(this.headerJson.getBytes(StandardCharsets.UTF_8));
//2.使用Base64加密载荷(payload)信息形成字符串
String payload = Base64.encodeBase64URLSafeString(this.payloadJson.getBytes(StandardCharsets.UTF_8));
//3.将头部字符串和载荷字符串用 点号 连接形成一个新的字符串
String content = String.format("%s.%s", header, payload);
//4.获取使用密钥加密后的签名
byte[] signatureBytes = this.algorithm.sign(content.getBytes(StandardCharsets.UTF_8));
//5.使用Base64加密签名(signature)信息形成字符串
String signature = Base64.encodeBase64URLSafeString(signatureBytes);
//将加密后的字符串连接后返回
return String.format("%s.%s", content, signature);
}
头部(header)

JWT有一个头部,头部用于描述JWT的基本信息,一共有两个属性

  • typ:用于描述token字符串的类型,默认会填入“JWT”
  • alg:签发时使用的签名或算法
载荷(payload)

载荷有固定的部分,也可以传入自定义的属性,自定义的内容可以是用户名、用户权限等,下面是固定的属性

  • iss:该JWT签发的主体,即谁生成了这个JWT
  • sub:该JWT的所有人,可以看成是客户端
  • aud:该JWT的接收对象
  • iat:一个时间戳,表示该JWT的签发时间
  • nbf:一个时间戳,表示该JWT的生效时间
  • exp:一个时间戳,表示该JWT的过期时间
  • jti:JWT的唯一标识符
签名(signature)

签名没有属性值,但是在形成签名时需要传入密钥

JWT Token实现

引入依赖

1
2
3
4
5
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.2.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
24
25
26
27
28
29
30
31
32
33
34
35
//获取指定过期时期和自定义载荷的token
/**
*
* @param expiryTime token存活时间,毫秒
* @param payloadClaims 传入的自定义键值对
* @return
* @throws UnsupportedEncodingException
*/
public static String getToken(long expiryTime,Map<String,String> payloadClaims) throws UnsupportedEncodingException {
//获取生成的时间
long currentTime = System.currentTimeMillis();
Date iat = new Date(currentTime);
//获取过期时间
Date exp = new Date(currentTime + expiryTime);
JWTCreator.Builder builder = JWT.create()
.withIssuer(iss)//设置签发主体
.withIssuedAt(iat)//设置生成时间
.withExpiresAt(exp);//设置过期时间
//设置自定义参数
Set<Map.Entry<String, String>> entries = payloadClaims.entrySet();
for (Map.Entry<String, String> entry : entries) {
builder.withClaim(entry.getKey(),entry.getValue());
}
return builder.sign(Algorithm.HMAC256(secret));
}


//解析字符串
public Map<String, Claim> verify(String token) throws UnsupportedEncodingException {
JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(secret)).withIssuer(iss).build();
DecodedJWT jwt = jwtVerifier.verify(token);
Map<String, Claim> claims = jwt.getClaims();
return claims;
//Map集合的值是Claim类型,若值是String则使用asString方法输出,日期类型使用asDate方法,以此类推
}
打赏