我创造了一份工作。我使用以下代码添加了一个步骤:
insert joblog select getdate(),SUSER_NAME(),current_user
exec msdb.dbo.sp_send_dbmail ...
该作业的所有者是
sa
。作为一名开发人员,我没有 sa 访问权限,但我有 sysadmin。
所以我将作业的所有者更改为 sa
。
作业运行良好并且电子邮件已发送。我为帮助我理解事情而创建的 [joblog] 表显示了
suser_name=NT SERVICE\SQLSERVERAGENT
current_user=dbo
现在,如果我转到代理的 UI,编辑(单个)作业步骤,选择“高级”页面,并将“以用户身份运行”填写为“dbo”,我会在 sp_send_dbmail 上收到 EXECUTE 拒绝。 [工作日志] 得到一行
susername=sa
current_user=dbo
错误原因是什么?
sa
显然可以运行proc。不仅; NT SERVICE\SQLSERVERAGENT
也可以!
我的疯狂猜测是,尽管在我的表中插入了 suser_name,“以用户身份运行”“选择”dbo 作为目标数据库中的用户,但没有任何与之关联的登录名,甚至没有
NT SERVICE\SQLSERVERAGENT
。
当模拟
USER
时(在本例中为 dbo
),任何外部数据库引用都将失败。 USER
是一个 database 对象,因此您的模拟仅限于数据库内的范围。当您尝试引用 msdb.dbo.sp_send_dbmail
时,您可能正在使用 3 部分命名,因为您不在 msdb
中(我不希望您这样做,因为您正在 INSERT
进入表格,并且不应该真正在系统数据库中完成)。
至于为什么你会得到
sa
,那是因为 LOGIN
dbo
所链接的是 USER
。如果 dbo
用户链接到不同的 LOGIN
,您将获得不同的 LOGIN
的名称。然而,这不意味着您可以通过冒充LOGIN
来冒充那个USER
;你绝对不能这样做。正如OP提到的是评论,这是记录。
“修复”是,如果您需要模拟,您可以模拟一个
LOGIN
,而不是 USER
,它可以访问您需要访问特定作业的所有数据库。