问题描述
虽然我们有解决方案,但我们想知道是否有更好的解决方案,因为我们的方案很丑陋,而且感觉超级错误。那么,有人知道使用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.getAdditional@R_393_4045@ion());
// <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.setAdditional@R_393_4045@ion(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.getAdditional@R_393_4045@ion());
// <custom-code>
refreshTokenInfo.remove("b");
// </custom-code>
refreshTokenInfo.put(TOKEN_ID,encodedRefreshToken.getValue());
refreshTokenInfo.put(ACCESS_TOKEN_ID,tokenId);
encodedRefreshToken.setAdditional@R_393_4045@ion(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 (将#修改为@)