【问题标题】:The server principal "sa" is not able to access the database "model" under the current security context服务器主体“sa”无法在当前安全上下文下访问数据库“模型”
【发布时间】:2013-04-25 10:19:12
【问题描述】:

我创建了一个存储过程,它执行一系列需要特殊权限的操作,例如创建数据库,恢复数据库等。我用

创建这个存储过程
execute as self

...使其作为 SA 运行。这是因为我想让一个没有任何权限的 SQL 用户只能运行我定义的这些命令。

但是当我运行这个存储过程时,我得到了

The server principal "sa" is not able to access the database "model" under the current security context.

为什么SA无法访问模型数据库?我实际上在 SA 下自己运行了存储过程中的代码,并且运行良好。

【问题讨论】:

    标签: sql-server execute-as


    【解决方案1】:

    在继续之前阅读Extending Database Impersonation by Using EXECUTE AS

    使用 EXECUTE AS USER 语句模拟主体时, 或在数据库范围的模块中使用 EXECUTE AS 子句, 默认情况下,模拟范围仅限于数据库。这 表示对数据库范围之外的对象的引用 将返回错误。

    您需要使用module signingHere 就是一个例子。

    【讨论】:

    • 谢谢,我去看看。
    【解决方案2】:

    对于其他来这里寻找此信息的人,这里是演示 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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-07
      • 1970-01-01
      • 2013-10-01
      • 2018-03-29
      相关资源
      最近更新 更多