使用dbo用户抛出的触发器“服务器主体无法访问数据库”

时间:2018-01-10 10:37:43

标签: sql-server tsql sql-server-2012 triggers

在一个数据库上运行的触发器以execute as owner运行,即使用户是两个数据库的dbo,也无法在运行时插入另一个数据库。

错误:服务器主体“AUser”无法访问当前安全上下文下的数据库“DatabaseB”。

示例触发器:

CREATE TRIGGER "MyTrigger"
ON "DatabaseA".dbo.MyTable
WITH EXECUTE AS OWNER
AFTER UPDATE
AS
BEGIN
    SET NOCOUNT ON;

    INSERT INTO DatabaseB.dbo."MyOtherTable" (ColumnA) VALUES ('test');
END
GO

“AUser”是DatabaseA和DatabaseB的DBO,更新“DatabaseA”.dbo.MyTable中的记录现在将导致服务器主体错误

编辑:在DatabaseA上启用TRUSTWORTHY修复此问题,但我宁愿不这样做

1 个答案:

答案 0 :(得分:3)

这是因为您已经使用了" WITH EXECUTE AS OWNER"子句。

当您的DML触发器/存储过程使用" WITH EXECUTE AS"时,模拟的主体是用户,而不是登录,您可以在此处清楚地看到它:

EXECUTE AS Clause (Transact-SQL)

enter image description here

  

' user_name'

     

指定模块内执行的语句   user_name中指定的用户的上下文。任何权限   模块中的对象将根据user_name进行验证。用户名   无法为具有服务器作用域或登录的DDL触发器指定   触发。请改用login_name。

因此,使用execute as user子句,您已在数据库中沙箱化了执行。

当您不使用此子句时,将通过登录执行过程/触发器,因此如果登录能够访问另一个数据库,则它将起作用。但是,通过以用户身份执行,您不再使用登录,因此即使所有者 sa ,您仍然会遇到相同的错误:< / p>

  

服务器主体&#34; sa&#34; 无法访问数据库   &#34; DatabaseB&#34;在当前的安全背景下。

解决此问题的不安全方法是让databaseA TRUSTWORTHY +其所有者获得AUTHENTICATE SERVER权限。

如果db_owners databaseA sysadmins不是sysadmin,则可以使用此功能,否则他们可以将权限提升为certificates

其他方式更复杂,但 secur e:使用c0 - c11 - c12 - c13 \ c21 - c22