2010-08-16 83 views
3

我正在使用一个系统,该系统必须根据另一个数据库中创建的对象在一个数据库中创建对象。对象不重复,所以我不能简单地复制对象。避免使用SET TRUSTWORTHY ON

我有下面的代码给出了我试图做的简化演示。如果您取消对ALTER DATABASE语句的注释,那么它将运行而没有任何错误。尽管如此,这有可能造成安全漏洞,所以我希望尽可能避免它。

我试过使用证书和模拟,但似乎没有工作。我认为DDL触发器在用户和登录时忽略了很多安全性。我也尝试在Test_DB_2中创建一个存储过程,它调用Test_DB_1中的SP,并让触发器调用该存储过程,但这也没有帮助。因此,如果你愿意接受它,你的挑战是让下面的代码在没有设置TRUSTWORTHY ON的情况下工作(或者如果有效的话打开数据库链接)。

感谢您的帮助,您可以给!

/************************ 
    SET-UP THE TEST 
************************/ 
USE master 
GO 
CREATE LOGIN Test_Security_Login WITH PASSWORD = '[email protected]!' 
CREATE DATABASE Test_DB_1 
CREATE DATABASE Test_DB_2 
GO 
USE Test_DB_1 
GO 
CREATE PROCEDURE dbo.Create_View 
AS 
BEGIN 
EXEC('CREATE VIEW Test_View AS SELECT 1 AS one') 
END 
GO 
CREATE USER Test_Security_User FOR LOGIN Test_Security_Login 
GRANT EXECUTE ON dbo.Create_View TO Test_Security_User 
GO 
USE Test_DB_2 
GO 
CREATE TRIGGER DDL_TRIGGER ON DATABASE WITH EXECUTE AS 'dbo' FOR DDL_VIEW_EVENTS 
AS 
BEGIN 
EXEC Test_DB_1.dbo.Create_View 
END 
GO 
CREATE USER Test_Security_User FOR LOGIN Test_Security_Login 
EXEC sp_addrolemember 'db_ddladmin', 'Test_Security_User' 

/************************ 
    RUN THE TEST 
************************/ 
USE Test_DB_2 
GO 
--ALTER DATABASE Test_DB_1 SET TRUSTWORTHY ON 
--ALTER DATABASE Test_DB_2 SET TRUSTWORTHY ON 
EXECUTE AS USER = 'Test_Security_User' 
GO 
CREATE VIEW dbo.Test_View_2 AS SELECT 2 AS two 
GO 
REVERT 
GO 

/************************ 
    CLEAN-UP 
************************/ 
USE master 
GO 
DROP DATABASE Test_DB_1 
DROP DATABASE Test_DB_2 
DROP LOGIN Test_Security_Login 
GO 

回答

7

太容易了。使用代码签名:

  • 创建自DB1中的签名证书
  • 标志使用证书
  • 下降私钥触发防止滥用
  • 出口证书到DB2(备份/从文件创建)
  • 从db2中的证书创建证书
  • 授予AUTHENTICATE和证书派生证书的任何其他必要权限
  • 利润

这是防弹的。有关完整的示例,请参见Call a procedure in another database from an activated procedure

+0

太容易了?不太...你不能签署DDL触发器:http://social.msdn.microsoft.com/Forums/en/sqlsecurity/thread/1333eecd-4c66-43d4-ab8f-03511cad4174;) – 2010-08-16 19:30:37

+1

D'oh。 ..好的,那么很难:不使用DDL触发器,而是使用事件通知。这会使视图添加异步(将在原始DDL提交后发生)。有几种方法:在[msdb]中具有过程的服务器级别EN,具有本地过程的db级别EN签名以访问x-db或db级别的EN,并在目标数据库中使用SSB x-db传递和过程执行。选择你最喜欢的,我会指导你如何去做。 – 2010-08-16 19:42:30

+4

我实际上可以通过使用存根过程调用DDL触发器的存根过程来使用EXECUTE AS以及使用GRANT AUTHENTICATE实现的证书来使其工作。我曾尝试过使用存根SP,并尝试使用证书,但我认为缺少的部分是AUTHENTICATE权限。一旦我把它降低到最低要求的权限,我会用完整的代码发布一个答案,但既然你指出我在正确的方向,我会接受你的答案。谢谢! – 2010-08-16 19:55:04