如何解决在Spring Security中生成JWT时,如何使访问令牌的有效负载与刷新令牌的有效负载不同?
虽然我们有解决方案,但我们想知道是否有更好的解决方案,因为我们的方案很丑陋,而且感觉超级错误。那么,有人知道使用Spring Security会有更好的解决方案吗?
问题
我们维护一个用于管理用户帐户的应用程序。登录时,我们生成两个JWT-访问令牌和刷新令牌。我们希望访问令牌的有效负载包含与刷新令牌不同的字段集。例如,如果 access 令牌的有效载荷为:
{
"a" : "foo","b" : "bar",}
我们希望 刷新 令牌的有效载荷为:
{
"a" : "foo","x" : "baz",}
我们做什么
我们唯一想到的解决方案是实现一个自定义令牌增强器,该增强器扩展了JwtAccessTokenConverter
并覆盖了enhance
方法,因此对超类方法的内容进行了很小的修改,以控制每个有效载荷的内容。这是代码:
public class CustomJwtAccessTokenConverter extends JwtAccessTokenConverter {
@Override
public OAuth2AccessToken enhance(
OAuth2AccessToken accessToken,OAuth2Authentication authentication
) {
DefaultOAuth2AccessToken result = new DefaultOAuth2AccessToken(accessToken);
Map<String,Object> info = new LinkedHashMap<>(accessToken.getAdditionalInformation());
// <custom-code>
info.remove("x");
// </custom-code>
String tokenId = result.getValue();
if (!info.containsKey(TOKEN_ID)) {
info.put(TOKEN_ID,tokenId);
} else {
tokenId = (String) info.get(TOKEN_ID);
}
result.setAdditionalInformation(info);
result.setValue(encode(result,authentication));
OAuth2RefreshToken refreshToken = result.getRefreshToken();
if (refreshToken != null) {
DefaultOAuth2AccessToken encodedRefreshToken = new DefaultOAuth2AccessToken(accessToken);
encodedRefreshToken.setValue(refreshToken.getValue());
// Refresh tokens do not expire unless explicitly of the right type
encodedRefreshToken.setExpiration(null);
try {
Map<String,Object> claims = jsonParser
.parseMap(JwtHelper.decode(refreshToken.getValue()).getClaims());
if (claims.containsKey(TOKEN_ID)) {
encodedRefreshToken.setValue(claims.get(TOKEN_ID).toString());
}
} catch (IllegalArgumentException e) {
}
Map<String,Object> refreshTokenInfo = new LinkedHashMap<>(
accessToken.getAdditionalInformation());
// <custom-code>
refreshTokenInfo.remove("b");
// </custom-code>
refreshTokenInfo.put(TOKEN_ID,encodedRefreshToken.getValue());
refreshTokenInfo.put(ACCESS_TOKEN_ID,tokenId);
encodedRefreshToken.setAdditionalInformation(refreshTokenInfo);
DefaultOAuth2RefreshToken token = new DefaultOAuth2RefreshToken(
encode(encodedRefreshToken,authentication));
if (refreshToken instanceof ExpiringOAuth2RefreshToken) {
Date expiration = ((ExpiringOAuth2RefreshToken) refreshToken).getExpiration();
encodedRefreshToken.setExpiration(expiration);
token = new DefaultExpiringOAuth2RefreshToken(encode(encodedRefreshToken,authentication),expiration);
}
result.setRefreshToken(token);
}
return result;
}
}
不同有效负载的上下文
我们有一个移动应用程序,需要将其访问权限和刷新令牌传递到Web视图。在Web视图中运行的应用程序没有后备服务器(由CDN提供的React Javascript应用程序)。我们的访问和刷新令牌包含从单独的单点登录系统发出的嵌套令牌,我们实际上是该单点登录系统的增强型代理。结果,我们发行的令牌相当大-我在自己的测试中生成了2000+个字符访问令牌。为了将令牌传递到Web视图,我们通过查询参数传递令牌。由于某些浏览器具有URL限制,我们希望SSO的访问令牌仅出现在我们的访问令牌中,而SSO的刷新令牌仅出现在我们的刷新令牌中,因为这将减轻URL膨胀-SSO的访问令牌已满- JWT,而其刷新令牌是简单的GUID。
我们知道,通过查询参数传递JWT并不是最佳实践,并且已经阅读了RFC。我们的任务期限很紧,这被认为是最快可行的解决方案。我们正在设计一种令牌交换微服务,以在将来解决此问题。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。