3.JWT的signature
JWT的第三部分是一个签名字符串,这一部分是将header的Base64编码和payload的Base64编码使用点号(.)连接起来之后,通过header声明的加密算法进行加密所得到的密文。为了保证安全,加密时需要加入盐(salt)。
下面是一个演示用例:用Java代码生成JWT令牌,然后对令牌的header部分字符串和payload部分字符串进行Base64解码,并输出解码后的JSON。
package com.crazymaker.demo.auth;
//省略import
@Slf4j
public class JwtDemo
{
@Test
public void testBaseJWT()
{
try
{
/**
*JWT的演示内容
*/
String subject = “session id”;
/**
*签名的加密盐
*/
String salt = “user password”;
/**
*签名的加密算法
*/
Algorithm algorithm = Algorithm.HMAC256(salt);
//签发时间
long start = System.currentTimeMillis() - 60000;
//过期时间,在签发时间的基础上加上一个有效时长
Date end = new Date(start + SessionConstants.SESSION_TIME_OUT *1000);
/**
*获取编码后的JWT令牌
*/
String token = JWT.create()
.withSubject(subject)
.withIssuedAt(new Date(start))
.withExpiresAt(end)
.sign(algorithm);
log.info(“token=” + token);
//编码后输出demo为:
//token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJzZXNza
W9uIGlkIiwiZXhwIjoxNTc5MzE1NzE3LCJpYXQiOjE1Nzg0NTE3MTd9.iANh9Fa0B_6H5TQ11bLCWcEpmWxuCwa2Rt6rnzBWteI
//以.分隔令牌
String[] parts = token.split(“\.” );
/**
*对第一部分和第二部分进行解码
*解码后的第一部分:header
*/
String headerJson =
StringUtils.newStringUtf8(Base64.decodeBase64(parts[0]));
log.info(“parts[0]=” + headerJson);
//解码后的第一部分输出的示例为: //parts[0]={“typ”:“JWT”,“alg”:“HS256”}
/**
*解码后的第二部分:payload
*/
String payloadJson;
payloadJson = StringUtils.newStringUtf8
(Base64.decodeBase64(parts[1]));
log.info(“parts[1]=” + payloadJson);
//输出的示例为:
//解码后的第二部分:parts[1]={“sub”:“session id”,“exp”:1579315535,“iat”:
1578451535}
} catch (Exception e)
{
e.printStackTrace();
}
}
…
}
在编码前的JWT中,payload部分JSON中的属性被称为JWT的声明。JWT的声明分为两类:
(1)公有的声明(如iat)。
(2)私有的声明(自定义的JSON属性)。
公有的声明也就是JWT标准中注册的声明,主要为以下JSON属性:
(1)iss:签发人。
(2)sub:主题。
(3)aud:用户。
(4)iat:JWT的签发时间。
(5)exp:JWT的过期时间,这个过期时间必须要大于签发时间。
(6)nbf:定义在什么时间之前该JWT是不可用的。
私有的声明是除了公有声明之外的自定义JSON字段,私有的声明可以添加任何信息,一般添加用户的相关信息或其他业务需要的必要信息。下面的JSON例子中的uid、user_name、nick_name等都是私有声明。
{
“uid”: “123…”,
“sub”: “session id”,
“user_name”: “admin”,
“nick_name”: “管理员”,
“exp”: 1579317358,
“iat”: 1578453358
}
下面是一个向JWT令牌添加私有声明的实例,代码如下:
package com.crazymaker.demo.auth;
//省略import
@Slf4j
public class JwtDemo
{
/**
*测试私有声明
*/
@Test
public void testJWTWithClaim()
{
try
{
String subject = “session id”;
String salt = “user password”;
/**
*签名的加密算法
*/
Algorithm algorithm = Algorithm.HMAC256(salt);
//签发时间
long start = System.currentTimeMillis() - 60000;
//过期时间,在签发时间的基础上加上一个有效时长
Date end = new Date(start + SessionConstants.SESSION_TIME_OUT *1000);
/**
*JWT建造者
*/
JWTCreator.Builder builder = JWT.create();
/**
*增加私有声明
*/
builder.withClaim(“uid”, “123…”);
builder.withClaim(“user_name”, “admin”);
builder.withClaim(“nick_name”,“管理员”);
/**
*获取编码后的JWT令牌
*/
String token =builder
.withSubject(subject)
.withIssuedAt(new Date(start))
.withExpiresAt(end)
.sign(algorithm);
log.info(“token=” + token);
//以.分隔,这里需要转义
String[] parts = token.split(“\.” );
String payloadJson;
/**
*解码payload
*/
payloadJson = StringUtils.newStringUtf8
(Base64.decodeBase64(parts[1]));
log.info(“parts[1]=” + payloadJson);
//输出demo为:parts[1]=
//{“uid”:“123…”,“sub”:“session id”,“user_name”:“admin”,
“nick_name”:“管理员”,“