我创建了一个存储过程,它执行一系列需要特殊权限的操作,例如:创建数据库,还原数据库等。我使用
创建此存储过程execute as self
...以便它作为SA运行。这是因为我想给一个没有任何权限的SQL用户只能运行我定义的这些命令。
但是当我运行这个存储过程时,我得到了
The server principal "sa" is not able to access the database "model" under the current security context.
为什么SA无法访问模型数据库?我实际上在SA下运行了存储过程中的代码,运行正常。
答案 0 :(得分:9)
继续阅读Extending Database Impersonation by Using EXECUTE AS。
使用EXECUTE AS USER语句模拟主体时, 或者在数据库范围的模块中使用EXECUTE AS子句, 默认情况下,模拟范围仅限于数据库。这个 表示对数据库范围之外的对象的引用 将返回错误。
您需要使用module signing。 Here就是一个例子。
答案 1 :(得分:0)
对于其他来这里寻找此信息的人来说,这里有一个示例代码,可以准确地演示OP(和我)想要的内容(基于上面Remus的优秀信息):
-- how to sign a stored procedure so it can access other Databases on same server
-- adapted from this very helpful article
-- http://rusanu.com/2006/03/01/signing-an-activated-procedure/
USE [master]
GO
CREATE DATABASE TempDB1
CREATE DATABASE OtherDB2
GO
USE TempDB1
GO
-- create a user for TempDB1
CREATE USER [foo] WITHOUT LOGIN
GO
CREATE PROCEDURE TempDB1_SP
AS
BEGIN
CREATE TABLE OtherDB2.dbo.TestTable (ID int NULL)
IF @@ERROR=0 PRINT 'Successfully created table.'
END
GO
GRANT EXECUTE ON dbo.TempDB1_SP TO [foo]
GO
EXECUTE AS User='foo'
PRINT 'Try to run an SP that accesses another database:'
EXECUTE dbo.TempDB1_SP
GO
REVERT
-- Output: Msg 916, Level 14, State 1, Procedure TempDB1_SP, Line 5
-- [Batch Start Line 14]
-- The server principal "..." is not able to access the database
-- "OtherDB2" under the current security context.
PRINT ''
PRINT 'Fix: Try again with signed SP...'
-- Create cert with private key to sign the SP with.
-- Password not important, will drop private key
USE TempDB1
GO
-- create a self-signed cert
CREATE CERTIFICATE [DB_Cert]
ENCRYPTION BY PASSWORD = 'Password1'
WITH SUBJECT = 'Signing for cross-DB SPs';
-- Sign the procedure with the certificate’s private key
ADD SIGNATURE TO OBJECT::[TempDB1_SP]
BY CERTIFICATE [DB_Cert]
WITH PASSWORD = 'Password1'
-- Drop the private key. This way it cannot be used again to sign other procedures.
ALTER CERTIFICATE [DB_Cert] REMOVE PRIVATE KEY
-- Copy the public key part of the cert to [master] database
-- backup to a file and create cert from file in [master]
BACKUP CERTIFICATE [DB_Cert] TO FILE = 'C:\Users\Public\DBCert.cer'
USE [OtherDB2] -- or use [master] = all DBs on server accessible
GO
CREATE CERTIFICATE [DB_Cert] FROM FILE = 'C:\Users\Public\DBCert.cer';
-- the 'certificate user' carries the permissions that are automatically granted
-- when the signed SP accesses other Databases
CREATE USER [DB_CertUser] FROM CERTIFICATE [DB_Cert]
GRANT CREATE TABLE TO [DB_CertUser] -- or whatever other permissions are needed
GO
USE TempDB1
EXECUTE dbo.TempDB1_SP
GO
-- output: 'Successfully created table.'
-- clean up: everything except the cert file, have to delete that yourself sorry
USE [master]
GO
DROP DATABASE TempDB1
DROP DATABASE OtherDB2
GO