我有一个使用OAuth身份验证的ASP.Net Core 2.1 Web API。另外,我们正在使用基于声明的身份验证,其中的声明编码在auth令牌中。
这已经运行了一段时间,但是最近出现了一个新要求,该要求从根本上使必须存储在令牌中的索取数量成倍增加,因此事情变得一发不可收拾。长话短说,现在我们处于auth令牌太长的地步,以至于我们不得不重新配置服务器以允许超过128k的标头。
这显然是站不住脚的;仅从网络流量的角度来看,必须发送100k的标头以及最简单的GET请求是荒谬的。因此,现在我在考虑以下几行:不用编码令牌中的声明,只需使用Guid令牌并将声明与令牌一起存储在 database 中,因此当我们验证令牌时我们可以同时提取索偿并在本地交换索偿。
从理论上讲,这应该一口气解决我们的整个问题,但是我只是停留在实现细节上,特别是:由于基于声明的身份验证期望找到auth令牌中编码的声明,因此我该如何交换排除包含所有声明的那个的Guid auth令牌?
现有代码:
public class MyAuthenticationEvents : OAuthValidationEvents
{
public override async Task ValidateToken(ValidateTokenContext context)
{
if (context.Properties.ExpiresUtc < DateTime.UtcNow)
{
context.Fail("Access Token has expired.");
return;
}
if (!await TokenIsValidAsync(context)) // code to validate the auth token against the database, could be modified to return claims
{
context.Fail("Access Token has not been properly set or has been invalidated.");
return;
}
// Here I would expect to do some skullduggery to switch the compact Guid token for a large token containing claims
context.Success();
}
}
正确的语法是什么?还是我在错误地树上吠叫,有一种完全更好的方法可以实现我的目标?
答案 0 :(得分:2)
您现有的身份验证中间件正在基于JWT的内容填充ClaimsPrincipal
上的声明,但是到您的授权处理程序检查声明时,它们并没有直接从令牌中读取,因此无需修改令牌本身。
您应该能够从中间件访问和修改当前用户(HttpContext.User
)声明,因此您可以使custom middleware在身份验证中间件之后执行,并根据数据库的结果添加声明查找。
编辑:正如Shaul在他的回答中指出的那样,这也可以在身份验证组件的Validate
方法中完成。在这种情况下,这实际上是个好地方。如果您希望将声明对数据库中声明的“转换”与身份验证过程脱钩,则可以使用单独的中间件(如我所述)。关键是ASP.NET Core将用户声明存储在ClaimsPrincipal
对象中,您只需要更新它,而不必担心令牌本身。
答案 1 :(得分:2)
结果非常简单。我需要在repoToken
方法中做的就是使用一个ValidateToken()
创建一个新的ClaimsPrincipal
,它是根据我存储在数据库中的序列化声明重新构建的:
ClaimsIdentity
仅需注意一件事:首次登录时,必须返回 ... // create claimsIdentity from serialized claims
context.Principal = new ClaimsPrincipal(claimsIdentity);
context.Success();
}
声明,因此在Subject
方法中,我们仍然需要:
HandleTokenRequest()