是否可以稍后在对象中调用 EXECUTE AS OWNER?

Is it possible to call EXECUTE AS OWNER later in object?

考虑这段代码:

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;

在每个 table 上,都有一项安全策略不允许更改 table 上的 TenantId 列,但绑定到数据库用户的列除外,但策略将允许 "sa" 用户。

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

我想要一个更好的解决方案,我可以在获得 TenantId 之后稍后在对象中调用 execute as owner。从逻辑上讲它是有效的,但问题是;他们实施了吗?您在代码中看到的 execute as login = 'sa' 不是一个好的解决方案,因为它要求当前登录能够模拟 sa 登录。

此触发器的要点是允许用户不在插入中指定 TenantId。 我什至不必在应用程序中提及 TenantId,一切都只在 SQL 服务器上。

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

我找到了一个解决方案,其中触发器调用用户禁止的模式中的过程。触发器没有 "with execute",可以获取 TenantId 并将该信息转发给过程。在此过程中,我有 "with execute as owner" 并且能够更改有关任何租户的记录。另外,我正在将 Inserted table 的所需列复制到临时文件 table 中,以便程序可以看到它,但我看不到解决方法。

更好的解决方案:

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;