Sql server 是否可以稍后在对象中调用EXECUTE作为所有者?

Sql server 是否可以稍后在对象中调用EXECUTE作为所有者?,sql-server,tsql,impersonation,execute-as,Sql Server,Tsql,Impersonation,Execute As,考虑以下代码: ALTER TRIGGER [dbo].[AfterInsertUpdateTenant_Korisnici] ON [dbo].[Korisnici] WITH EXECUTE AS OWNER FOR INSERT AS DECLARE @TenantId INT = dbo.GetCurrentTenantId(); EXECUTE AS LOGIN = 'sa'; UPDATE Korisnici SET TenantId = @Te

考虑以下代码:

ALTER TRIGGER [dbo].[AfterInsertUpdateTenant_Korisnici] 
ON [dbo].[Korisnici]
WITH EXECUTE AS OWNER
FOR INSERT
AS
    DECLARE @TenantId INT = dbo.GetCurrentTenantId();

    EXECUTE AS LOGIN = 'sa';

    UPDATE Korisnici
    SET TenantId = @TenantId
    FROM Inserted i
    WHERE Korisnici.Id = i.Id;

    REVERT;
在每个表上,都有一个安全策略,除了绑定到数据库用户的列外,该策略不允许更改表上的
TenantId
列,但该策略允许“sa”用户更改

问题是
TenantId
,我需要通过调用主体获取
TenantId
,因为
TenantId
绑定到数据库用户。我知道一种解决方案:在触发器中不使用带有execute的
,在我获得
TenantId
并将其传递到一个过程中之后,调用带有带有execute的
的过程,但随后我必须将插入的表复制到temp表中,以便我可以在过程中访问它

我想要一个更好的解决方案,在我获得
TenantId
之后,我可以稍后在object中调用
executeasowner
。从逻辑上讲,这是正确的,但问题是;他们实施了吗<代码>作为登录名执行='sa'
您可以在代码中看到这不是一个好的解决方案,因为它要求当前登录名能够模拟
sa
登录名

此触发器的作用是允许用户在插入时不指定
TenantId
。 我甚至不必在应用程序中提到
TenantId
,所有内容都只在SQL Server上


另一个解决方案是,如果对象的创建者可以在安全策略中写入我可以读取的对象的一些信息,并基于这些信息允许用户更新
TenantId
。它甚至可能是对对象的权限,但问题是如何读取导致调用安全策略的对象?

我找到了一个解决方案,其中触发器调用用户禁止的模式中的过程。触发器没有“with execute”,可以获取TenantId并将该信息转发给过程。在这个过程中,我拥有“以所有者身份执行”,并且能够更改关于任何租户的记录。此外,我正在将插入表所需的列复制到临时表中,以便过程可以看到它,我看不到解决方法

更好的解决方案:

alter trigger [dbo].[AfterInsertUpdateTenant_Korisnici]
on [dbo].[Korisnici]
with execute as owner
for insert 
as 
execute as user = original_login();
declare @TenantId int = dbo.GetCurrentTenantId();
revert;

update dbo.Korisnici
set TenantId = @TenantId
from Inserted i
where dbo.Korisnici.Id = i.Id;

您可能有XY问题…如果您的权限设置正确,我无法理解您为什么需要尝试这样的事情…我可能会,但如果我想使用多租户并拥有一个安全的系统,我没有任何其他解决方案。具有灵活性、安全性和维护简单性。使用此系统,每个数据库可能有多个租户,也可能没有。如果是多租户,请在数据库前面放置一个服务……这是一个桌面应用程序,创建一个服务是一项繁琐而持久的任务。我不是从头开始创建它,只是升级它……不幸的是,这也是构建解决方案的“正确”方法。另一种可能性(我强调我可能不会这样做)是创建一个存储过程或函数,它在DB的所有入口点开始时被调用,用于检查客户端权限。。。。