sql server在触发器中执行权限错误

时间:2009-11-10 16:39:35

标签: sql-server sql-server-2008 triggers

我有一个触发器,我想发送一封关于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 个答案:

答案 0 :(得分:15)

这是由于execute-as-user scoping - 上下文切换到数据库级用户默认情况下仅限于该数据库(并且上面的代码在给定数据库之外执行到msdb),并且仅限数据库验证者无效。有关如何解决/解决方法的多种选项,请参阅上面的链接。

答案 1 :(得分:10)

触发器的EXECUTE AS与EXECUTE AS USER = '...'相同,与EXECUTE AS LOGIN = '...'不同。 chadhoc已经指出了EXECUTE AS模拟上下文及其约束的链接。基本上,因为触发器的EXECUTE AS子句由dbo保证,而不是由sysadmin保证,所以它仅在数据库的上下文中受信任。

有两种选择:

  1. 一个大小适合所有大锤:ALTER DATABASE <yourdb> SET TRUSTWORTHY ON;。这将提升数据库标记为可信,并且执行上下文可以在数据库之外,如果拥有数据库的登录具有propper权限。这不建议在高度安全的环境中使用,因为如果没有适当的限制,它会打开各种特权提升的大门,并且很难适当地约束。

  2. 手术切除选项:代码签名。有关示例,请参阅Call a procedure in another database from an activated procedure。这不适合胆小的人,它涉及几个复杂的步骤:生成证书,签署过程,删除私钥,将证书复制到msdb,创建从msdb中的证书派生的用户,在证书上授予认证数据库派生用户,在证书派生用户的sp_send_mail上执行grante EXECUTE。任何这些步骤中的任何错误都会导致整个序列无用,因此非常容易搞砸,但从安全的角度来看,结果是绝对的防弹。

答案 2 :(得分:0)

从触发器发送电子邮件是个坏主意。如果电子邮件服务器关闭,您不希望无法更改数据。

最好将电子邮件的信息发送到另一个表,然后该表从定期运行的作业发送电子邮件。一个运行说每五分​​钟一次。

还有一些名为Service Broker的东西,我以前没用过,可以帮助完成这项任务,你可能想看一下。