在与Autofac集成时,如何使用JWT识别租户?

在与Autofac集成时,如何使用JWT识别租户?,jwt,autofac,multi-tenant,asp.net-core-webapi,Jwt,Autofac,Multi Tenant,Asp.net Core Webapi,我正在尝试构建一个多租户ASP.NET Core 2.1 WebApi。 我想从jwt令牌中选择租户,而不是从url或端口。 因此,当用户请求令牌时,我将其租户id放入令牌中。 但当我试图解决Autofac多租户策略(ITenantIdentificationsStrategy)中的租户时,如下所示: public bool TryIdentifyTenant(out object tenantId) { _logger.LogInformation("*********

我正在尝试构建一个多租户ASP.NET Core 2.1 WebApi。 我想从jwt令牌中选择租户,而不是从url或端口。 因此,当用户请求令牌时,我将其租户id放入令牌中。 但当我试图解决Autofac多租户策略(ITenantIdentificationsStrategy)中的租户时,如下所示:

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中


如何做到这一点?

这个简短版本是你不能免费做到这一点。这就是为什么最好使用你可以信任但不需要额外支持的东西(比如请求中的主机名)

如果您只能信任令牌,那么我已经看到了大致做到这一点的解决方案(在伪代码-that-looks-like-C#中):

这样做的风险在于,您可能会受到攻击,其中有人发送了一个格式错误的令牌,该令牌的寿命仅足以通过您请求管道的初始部分。令牌将无法通过验证,因此常规安全性应该处理它,但在运行之前,租户值没有经过正式验证。如果你有管道逻辑,例如。。。第一次提出要求或诸如此类的要求时,自动提供新租户?。。。那你可能有麻烦了。有人可能会随机生成数以百万计的租户名称并杀死您的数据库。在这种情况下,您有时可以使用主机名等其他内容


或者,您可以在
ManuallyLookAtToken()
方法中手动调用令牌验证逻辑,并在继续之前确保其有效。这有点痛苦,但并非不可能。这就意味着,在任何给定的请求下,技术上你都会运行两次,而且代价很高,所以如果你走到这条路线上,考虑一下PERP,平衡它的安全性。

谢谢,”特拉维斯对此进行了广泛的解释。我想我可以通过某种方式将令牌身份验证移到管道的上层,以便在Autofac租户识别之前进行。我之所以要这样做,是因为每个租户都有数据库连接字符串,所以我可以为每个租户实例化不同的数据库。
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"];