ServiceStack - [Authenticate] 属性在请求过滤器之前被调用。不适用于 OrmLiteMultitenancyAuthRepository / OrmLiteCacheClient

ServiceStack - [Authenticate] attribute is called before request filters. Does not work with OrmLiteMultitenancyAuthRepository / OrmLiteCacheClient

我有一个多租户应用程序,每个租户 postgres 数据库都有一个模式

数据库包含以下模式:

tenant_cf5f3518bd524c3797b884457b374e50
tenant_46255f07079046139f8c0f94290885cd
tenant_620ef0de80f74f95992742e8db4b153f
tenant_6d93b51d61ed4e33a5fb324845a83603
tenant_8e0fd300a3124de29a3070b89f3662ed
...

我在 async 请求过滤器的 IRequest.Items 上设置了 TenantId

TenantIdFilter.cs
-----------------
var aHasTenant = dto as IHaveTenant;
if (aHasTenant == null) return;
if (hasTenant.TenantId == Guid.Empty)
{
    var error = DtoUtils.CreateErrorResponse(req, HttpError.BadRequest("Missing tenant id"));
    await res.WriteToResponse(req, error);
}
if (!req.GetSession().IsAuthenticated){
    var error = DtoUtils.CreateErrorResponse(req, HttpError.Unauthorized("Unauthorized"));
    await res.WriteToResponse(req, error);
    req.Items.Remove("TenantId")
}
req.Items.Add("TenantId", hasTenant.TenantId);

...

appHost.GlobalAsyncRequestFilters.Add(new TenantIdFilter().Invoke);

我已经设置了 AppHost.GetDbConnection() 来检索每个租户的连接。这一切都很好。我已经设置了要包含的 postgres 连接字符串。

var connectionString = AppSettings.GetString('ConnectionString');
if (req.Items.ContainsKey("TenantId")){
  var tenantId = (Guid)req.Items["TenantId"];
  connectionString = connectionString + ';Search Path=tenant_{tenantId}'
}
return new OrmLiteDbConnectionFactory(connectionString).Open()
...

当我使用 [Authenticate] 属性时出现问题(我怀疑 roles/permissions 属性也会发生同样的情况)。

[Authenticate]
public class RestrictedDto : IReturnVoid {
}

似乎 [Authenticate] 过滤器在任何 GlobalRequestFilter 之前被调用。这意味着 TenantId 不会设置在 IRequest.Items 上。因此,GetDbConnection(IRequest request) 将检索无效的 IDbConnection(不会采用 TenantId,因为它还不存在)。

Authenticate 过滤器尝试从 ICacheClient 检索会话信息时,ICacheClient (OrmLiteCacheClient) 从 [=] 检索 DbConnection 16=]。然后它抛出一个错误,指出 cache_entry table 没有找到。

我希望 TenantIdFilter.cs 在任何 [Authenticate] 属性之前是 运行。我该怎么做?

也许我可以在 AppHost ?

中覆盖一个方法

身份验证属性是 Request Filter attribute which by design has the lowest priority of all built-in attributes 以防止未经授权的请求执行应用程序逻辑。

您可以在自定义 GetDbConnection() 中解析租户,其中请求 DTO 可从 IRequest.Dto 属性 获得,例如:

public override IDbConnection GetDbConnection(IRequest req = null)
{
    var tenantId = req?.Dto is IHaveTenant hasTenant ? hasTenant.TenantId : (Guid?) null;
}