SQL Server выполнить как ошибки разрешения в триггере - PullRequest
10 голосов
/ 10 ноября 2009

У меня есть триггер, где я хочу отправить электронное письмо с обновлениями строки в таблице SalesClosing. Теперь пользователь (dbuser), который выполняет триггер, имеет очень ограниченные разрешения. Поэтому я хочу, чтобы триггер выполнялся как dbmailuser. Пользователь, у которого есть права на отправку электронной почты. Я проверил, что dbmailuser может выполнять sp_send_dbmail при входе в систему как этот пользователь. Когда срабатывает триггер, я получаю сообщение об ошибке: невозможно выполнить sp_send_dbmail. Поэтому я вошел как dbuser , запустил EXECUTE AS LOGIN = 'dbmailuser'; и был в состоянии выполнить sp_send_dbmail. Теперь, почему я не могу сделать это в триггере. Я использую SQL Server 2008. Ниже приведен триггер ddl.

alter TRIGGER SalesClosingTrigger ON SalesClosing
WITH EXECUTE AS 'dbmailuser'
for insert, update
AS
BEGIN
  EXEC msdb.dbo.sp_send_dbmail
  --@profile_name = 'Test_Email_Profile',
  @recipients='testemail@test.com',
  @body = 'This is a test for Database Mail.',
  @body_format = 'TEXT',
  @subject = 'Database Mail Test'
END 
GO

Ответы [ 3 ]

15 голосов
/ 10 ноября 2009

Это связано с выполнением при определении пользователем - переключение контекста на пользователя уровня базы данных по умолчанию ограничено только этой базой данных (и приведенный выше код выполняется вне данной базы данных вплоть до msdb ), а аутентификатор только для базы данных недействителен. См. Ссылку выше для нескольких вариантов решения / обхода.

10 голосов
/ 10 ноября 2009

EXECUTE AS триггера такой же, как EXECUTE AS USER = '...', а не EXECUTE AS LOGIN = '...'. chadhoc уже указал на ссылку на контекст олицетворения EXECUTE AS и его ограничения. По сути, поскольку условие EXECUTE AS триггера гарантируется dbo, а не sysadmin, ему доверяют только в контексте базы данных.

Есть две альтернативы:

  1. Один размер подходит для всех кувалд: ALTER DATABASE <yourdb> SET TRUSTWORTHY ON;. Это повысит пометку базы данных как доверенной, и контекст выполнения может выйти за пределы базы данных, , если у loggin, которому принадлежит база данных, есть права propper . Это не рекомендуется в высокозащищенной среде, поскольку это открывает двери для различного уровня привилегий, если не правильно ограничено, и очень трудно правильно ограничить.

  2. Вариант хирургической прецессии: подписание кода. См. Вызов процедуры в другой базе данных из активированной процедуры для примера. Это не для слабонервных, он включает в себя несколько сложных шагов: создать сертификат, подписать процедуру, сбросить закрытый ключ, скопировать сертификат в msdb, создать пользователя, полученного из сертификата в msdb, предоставить базу данных аутентификации на сертификате производный пользователь, предоставьте EXECUTE для sp_send_mail для полученного сертификата пользователя. Любая ошибка на любом из этих этапов сделает всю последовательность бесполезной, поэтому ее очень легко испортить, но результат с точки зрения безопасности является абсолютно пуленепробиваемым.

0 голосов
/ 10 ноября 2009

Отправка электронного письма из триггера - плохая идея. Вы не хотите, чтобы вы могли вносить изменения в данные, если почтовый сервер не работает.

Лучше отправить информацию для электронного письма в другую таблицу, которая затем отправляет электронное письмо от периодически выполняемой работы. Тот, который бежит, скажем, каждые пять минут.

Существует также нечто, называемое Service Broker, которое я раньше не использовал, которое может помочь в этой задаче, вы можете посмотреть на это.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...