一、JWT令牌介绍
通过上边的测试我们发现,当资源服务和授权服务不在一起时资源服务使用RemoteTokenServices 远程请求授权服务验证token,如果访问量较⼤将会影响系统的性能。
解决上边问题: 令牌采用JWT格式即可解决上边的问题,用户认证通过会得到一个JWT令牌,JWT令牌中已经包括了用户相关的信 息,客户端只需要携带JWT访问资源服务,资源服务根据事先约定的算法自行完成令牌校验,无需每次都请求认证服务完成授权。
1、什么是JWT?
JSON Web Token(JWT)是一个开放的行业标准(RFC 7519),它定义了一种简洁的、自包含的协议格式,用于在通信双方传递json对象,传递的信息经过数字签名可以被验证和信任。JWT可以使用HMAC算法或使用RSA的公钥/私钥对来签名,防止被篡改。
2、JWT令牌结构
JWT令牌由三部分组成,每部分中间使用点(.)分隔,比如:xxxxx.yyyyy.zzzzz
①Header
头部包括令牌的类型(即JWT)及使用的哈希算法(如HMAC SHA256或RSA),例如
{
"alg": "HS256",
"typ": "JWT"
}
将上边的内容使用Base64Url编码,得到一个字符串就是JWT令牌的第一部分。
②Payload
第二部分是负载,内容也是一个json对象,它是存放有效信息的地方,它可以存放jwt提供的现成字段,比 如:iss(签发者),exp(过期时间戳), sub(⾯向的用户)等,也可自定义字段。 此部分不建议存放敏感信息,因为此部分可以解码还原原始内容。 最后将第二部分负载使用Base64Url编码,得到一个字符串就是JWT令牌的第二部分。 一个例子:
{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022
}
③Signature
第三部分是签名,此部分用于防止jwt内容被篡改。 这个部分使用base64url将前两部分进行编码,编码后使用点(.)连接组成字符串,最后使用header中声明 签名算法进行签名。
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
base64UrlEncode(header):jwt令牌的第一部分。
base64UrlEncode(payload):jwt令牌的第二部分。
secret:签名所使用的密钥。
二、认证服务器JWT改造(Authorization Server)
lagou-cloud-oauth-server-9999–》OauthServerConfigurer
需要调整3处

/**
* 该方法用于创建tokenStore对象(令牌存储对象)
* token以什么形式存储
*
* @return
*/
private TokenStore tokenStore() {
// return new InMemoryTokenStore();
return new JwtTokenStore(jwtAccessTokenConverter());
}
/**
* 返回jwt令牌转换器(帮助我们⽣成jwt令牌的)
* 在这⾥,我们可以把签名密钥传递进去给转换器对象
*
* @return
*/
public JwtAccessTokenConverter jwtAccessTokenConverter() {
JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter();
jwtAccessTokenConverter.setSigningKey(sign_key);// 签名密钥
jwtAccessTokenConverter.setVerifier(new MacSigner(sign_key)); // 验证时使用的密钥,和签名密钥保持一致
return jwtAccessTokenConverter;
}
/**
* 该方法用户获取一个token服务对象(该对象描述了token有效期等信息)
*
* @return
*/
private AuthorizationServerTokenServices authorizationServerTokenServices() {
DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
defaultTokenServices.setSupportRefreshToken(true); // 是否开启令牌刷新
defaultTokenServices.setTokenStore(tokenStore());
// 设置令牌有效时间(一般设置为2个小时)
defaultTokenServices.setAccessTokenValiditySeconds(20);// 20秒
// 设置刷新令牌的有效时间
defaultTokenServices.setRefreshTokenValiditySeconds(3 * 24 * 60 * 60);
// 针对jwt添加配置
defaultTokenServices.setTokenEnhancer(jwtAccessTokenConverter());
return defaultTokenServices;
}
说明

三、资源服务器校验JWT令牌
lagou-service-autodeliver-8098—》ResourceServerConfigurer
不需要和远程认证服务器交互,添加本地tokenStore
1、ResourceServerConfigurer
/**
* 该方法用于定义资源服务器向远程认证服务器发起请求,进行token校验等事宜
*
* @param resources
* @throws Exception
*/
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
// super.configure(resources);
/*// 1、设置当前资源服务的资源id
resources.resourceId("autodeliver");
// 2、定义token服务对象(token校验就应该靠token服务对象)
RemoteTokenServices remoteTokenServices = new RemoteTokenServices();
// 校验端点/接⼝设置
remoteTokenServices.setCheckTokenEndpointUrl("http://localhost:9999/oauth/check_token");
remoteTokenServices.setClientId("client_lagou123");
remoteTokenServices.setClientSecret("abcxyz");
resources.tokenServices(remoteTokenServices);*/
// jwt令牌改造:不需要和远程认证服务器交互,添加本地tokenStore
resources.resourceId("autodeliver").tokenStore(tokenStore()).stateless(true);// 无状态设置
}
2、将以下代码从上面的类中直接拷贝过来
//***************************************** 复用【开始】 *****************************************
// 直接从com.lagou.edu.config.OauthServerConfigurer拷贝过来
/**
* 该方法用于创建tokenStore对象(令牌存储对象)
* token以什么形式存储
* @return
*/
private TokenStore tokenStore() {
// return new InMemoryTokenStore();
return new JwtTokenStore(jwtAccessTokenConverter());
}
/**
* 返回jwt令牌转换器(帮助我们⽣成jwt令牌的)
* 在这⾥,我们可以把签名密钥传递进去给转换器对象
* @return
*/
public JwtAccessTokenConverter jwtAccessTokenConverter(){
JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter();
jwtAccessTokenConverter.setSigningKey(sign_key);// 签名密钥
jwtAccessTokenConverter.setVerifier(new MacSigner(sign_key)); // 验证时使用的密钥,和签名密钥保持一致
return jwtAccessTokenConverter;
}
//***************************************** 复用【结束】 *****************************************
四、测试
获取token的接口返回值已经变成这样的了
本文介绍了JWT令牌的原理和结构,包括其包含的Header、Payload和Signature三部分。文章详细阐述了如何将认证服务器进行JWT改造,包括创建JWTTokenStore、JWTAccessTokenConverter以及设置签名密钥。同时,资源服务器不再依赖远程认证服务器,而是通过本地tokenStore进行JWT令牌的校验,实现无状态设置。

876

被折叠的 条评论
为什么被折叠?



