OAuth2前置知识-JWT相关
什么是jwt
(小提示:其实也不是什么OAuth2的前置知识,只是后面会用到相关知识。主要是不知道起什么标题,哈哈哈哈

)
jwt 名称为 Java Web Token ,其实就是一个字符串,只是它的格式是 xxxx.yyyy.zzzz。
官方解释是这样的:
Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该token被设计为紧凑且安全的,特别适用于分布式站点的单点登录(SSO)场景。JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,该token也可直接被用于认证,也可被加密。
其实就是这样的:用户输入用户名密码后,认证服务器通过用户名和密码生成一个token字符串返回给浏览器,然后浏览器通过这个头部带着这个token就可以请求得到相应的资源了:

这是一个token的字符串:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9. eyJleHAiOjE2NDA2MTQ2ODgsInVzZXJfbmFtZSI6Imh4eCIsImp0aSI6IjBiNDkwYzRkLTE1N2UtNGU2MS04Mzk0LWVlNjAxOWQ4NGE3NCIsImNsaWVudF9pZCI6ImNsaWVudDEiLCJzY29wZSI6WyJhbGwiXX0. 5Vc65_KIl_2Bx_XOZPotrQxAAJWCJGHSKvXaGNH20XA
例如,我把这个xxxx.yyyy.zzzz 的字符串放在 jwt官网进行解析
就可以看到如下的东东:

也就是说这样格式的一个字符串可以解析为一个json格式的对象。
那么xxxx yyyy zzzz 分别是一些什么?
xxxx yyyy zzzz
xxxx 称为头部字符串
xxxx 是header
也就是上图的
{
"alg": "HS256",
"typ": "JWT"
}
它描述的是jwt的元数据,alg表示签名的算法,typ表示这个令牌的类型,然后将header通过base64Url(header)就得到了xxxx字符串
yyyy 称为负载 payload字符串
payload 称为负载,也是一个json对象,一般用来存放实际的数据信息,jwt一般有如下的字段
{
"iss":"签发人",
"exp":"过期时间",
"sub":"主题",
"aud":"受众",
"nbf":"生效时间",
"iat":"签发时间",
"jti":"jwt的ID,一个编号",
}
然后yyyy=basey64Url(payload)。
zzzz 称为签名字符串
签名字符串是由如下公式所得:
zzzz= HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), 'your-256-bit-secret')
也就是说JWT的第三部分是将header的Base64编码和payload的Base64编码通过“.”点号连接起来之后,通过header部分的加密算法进行加密所得到的的密文,为了保证安全,加密时需要加入盐salt
your-256-bit-secret:你的秘钥
头部编码加payload编码,加上你的秘钥通过HMACSHA256签名算法得到一个签名zzzz
得到了签名,然后 xxxx yyyy zzzz 通过“.”连接起来,就得到了一个token字符串
下面通过一个简单的栗子来说明下
栗子
/**
* @author hxx
* @date 2022/2/8
*/
@Slf4j
public class JwtDemo {
@Test
public void test(){
//主题
String subject = "subject";
//签名的加密盐
String salt = "your 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输出
/**
* eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJzZXNzaW9uX2lkIiwiZXhwIjoxNjQ0MzQwMTkzLCJpYXQiOjE2NDQzMDc3OTN9.OiC6mKB6BGhAjTgqream-iNISFdpgkxz3xeuSMnRyPY
*/
//以.号分割令牌
String[] split = token.split("\\.");
//解码的第一部分
String header = StringUtils.newStringUtf8(Base64.decodeBase64(split[0]));
log.info("header: "+header);
//解码后的输出为
/**
* header: {"typ":"JWT","alg":"HS256"}
*/
//解码的第二部分
String payload = StringUtils.newStringUtf8(Base64.decodeBase64(split[1]));
log.info("payload: "+payload);
//解码后的输出为
/**
* payload: {"sub":"subject","exp":1644340694,"iat":1644308294}
*/
}
}

浙公网安备 33010602011771号