Можно ли вызвать EXECUTE AS OWNER позже в объекте?
Рассмотрим этот код:
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
привязан к пользователю базы данных. Я знаю одно решение: без with execute
в триггере и вызывая процедуру, которая имеет with execute
после того как я получу TenantId
и передать его в процедуру, но тогда мне придется скопировать таблицу Inserted во временную таблицу, чтобы я мог получить к ней доступ в процедуре.
Я хотел бы лучше решение, где я могу позвонить execute as owner
позже в объекте, после того как я получу TenantId
, Логически это верно, но вопрос в том, они реализовали это? execute as login = 'sa'
то, что вы видите в коде, не является хорошим решением, поскольку требует, чтобы текущий логин мог выдавать себя за sa
авторизоваться.
Смысл этого триггера состоит в том, чтобы позволить пользователю не указывать TenantId
на вкладыше. Я не должен даже упоминать TenantId
в приложении все только на SQL Server.
Другое решение было бы, если бы создатель объекта мог написать некоторую информацию об объекте, которую я мог бы прочитать в политике безопасности и на основе этой информации позволить пользователю обновить TenantId
, Это могут быть даже разрешения на объект, но вопрос в том, как я могу прочитать, какой объект вызвал вызов политики безопасности?
1 ответ
Я нашел решение, в котором триггер вызывает процедуру, которая в схеме запрещена для пользователя. Триггер не имеет "with execute" и может получить TenantId и переслать эту информацию в процедуру. В процедуре я имею "с исполнителем как владелец" и могу изменять записи, касающиеся любого Арендатора. Кроме того, я копирую необходимые столбцы таблицы Inserted в временную таблицу, чтобы процедура могла это увидеть, но я не вижу способа обойти это.
Еще лучшее решение:
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;