与 Autofac 集成时如何识别使用 JWT 的租户?
How do you identify the tenant using a JWT when integrating with Autofac?
我正在尝试构建多租户 ASP.NET Core 2.1 WebApi。
我想从 jwt 令牌而不是 url 或端口中选择租户。
因此,当用户请求令牌时,我将其 tenant_id 放入令牌中。
但是当我尝试像这样解析 Autofac 多租户策略 (ITenantIdentificationStrategy) 中的 TenantId 时:
public bool TryIdentifyTenant(out object tenantId)
{
_logger.LogInformation("***********************************TryIdentify");
tenantId = null;
try
{
var context = _httpContextAccessor()?.HttpContext;
if(context != null && context.Request != null)
{
var id = context.User.FindFirst("tenantId")?.Value;
if (id != null)
{
tenantId = id;
}
}
}
catch(Exception)
{
// Happens at app startup in IIS 7.0
}
return tenantId != null;
}
我看到 context.User 没有填充 jet,那是因为 Jwt 身份验证没有发生 jet。
怎么做?
这个的简短版本是你不能免费做这个。这通常就是为什么最好使用你可以信任但不需要额外的东西的原因支持使用(如请求中的主机名)。
如果您只能信任令牌,那么我已经看到 大致 执行此操作的解决方案(在伪代码中看起来像 C#):
if(context.Items["tenant"] == null && context.User == null)
{
// no tenant has been identified before and
// token validation hasn't happened so manually
// get the tenant from the token knowing you are
// potentially getting an untrusted value.
context.Items["tenant"] = ManuallyLookAtToken();
}
else if(context.Items["tenant_trusted"] == null && context.User != null)
{
// a "trusted" tenant ID hasn't been read from the user
// principal so let's update.
context.Items["tenant"] = GetTenantFrom(context.User);
context.Items["tenant_trusted"] = true;
}
return context.Items["tenant"];
这样做的风险在于,您可能会受到攻击,即有人发送格式错误的令牌,该令牌的寿命仅够通过请求管道的初始部分。令牌不会通过验证,因此常规安全性应该处理它,但在此之前 运行s 租户值未被正式验证。如果你有管道逻辑,例如......在第一次请求时自动提供新租户或类似的东西?......那么你可能会有麻烦。有人可以随机生成数百万个租户名称并杀死您的数据库。在这种情况下,您有时可以回退到主机名等其他内容。
或者,您实际上可以手动调用该 ManuallyLookAtToken()
方法中的令牌验证逻辑,并在继续之前确保其有效。这有点痛苦,但并非不可能。这意味着从技术上讲,您将 运行 在任何给定请求期间执行两次,而且它有点昂贵,因此如果您采用该路线并在安全隐患之间取得平衡,请考虑性能。
我正在尝试构建多租户 ASP.NET Core 2.1 WebApi。 我想从 jwt 令牌而不是 url 或端口中选择租户。 因此,当用户请求令牌时,我将其 tenant_id 放入令牌中。 但是当我尝试像这样解析 Autofac 多租户策略 (ITenantIdentificationStrategy) 中的 TenantId 时:
public bool TryIdentifyTenant(out object tenantId)
{
_logger.LogInformation("***********************************TryIdentify");
tenantId = null;
try
{
var context = _httpContextAccessor()?.HttpContext;
if(context != null && context.Request != null)
{
var id = context.User.FindFirst("tenantId")?.Value;
if (id != null)
{
tenantId = id;
}
}
}
catch(Exception)
{
// Happens at app startup in IIS 7.0
}
return tenantId != null;
}
我看到 context.User 没有填充 jet,那是因为 Jwt 身份验证没有发生 jet。
怎么做?
这个的简短版本是你不能免费做这个。这通常就是为什么最好使用你可以信任但不需要额外的东西的原因支持使用(如请求中的主机名)。
如果您只能信任令牌,那么我已经看到 大致 执行此操作的解决方案(在伪代码中看起来像 C#):
if(context.Items["tenant"] == null && context.User == null)
{
// no tenant has been identified before and
// token validation hasn't happened so manually
// get the tenant from the token knowing you are
// potentially getting an untrusted value.
context.Items["tenant"] = ManuallyLookAtToken();
}
else if(context.Items["tenant_trusted"] == null && context.User != null)
{
// a "trusted" tenant ID hasn't been read from the user
// principal so let's update.
context.Items["tenant"] = GetTenantFrom(context.User);
context.Items["tenant_trusted"] = true;
}
return context.Items["tenant"];
这样做的风险在于,您可能会受到攻击,即有人发送格式错误的令牌,该令牌的寿命仅够通过请求管道的初始部分。令牌不会通过验证,因此常规安全性应该处理它,但在此之前 运行s 租户值未被正式验证。如果你有管道逻辑,例如......在第一次请求时自动提供新租户或类似的东西?......那么你可能会有麻烦。有人可以随机生成数百万个租户名称并杀死您的数据库。在这种情况下,您有时可以回退到主机名等其他内容。
或者,您实际上可以手动调用该 ManuallyLookAtToken()
方法中的令牌验证逻辑,并在继续之前确保其有效。这有点痛苦,但并非不可能。这意味着从技术上讲,您将 运行 在任何给定请求期间执行两次,而且它有点昂贵,因此如果您采用该路线并在安全隐患之间取得平衡,请考虑性能。