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;
}
我有一个多租户应用程序,每个租户 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;
}