SQL在创建数据库时授予其他用户db_owner

时间:2013-04-02 12:28:48

标签: sql sql-server triggers

我想设置一个MS SQL触发器(或其他一些机制),它会自动授予某些组db_owner权限。

希望我们的用户在SQL Server上拥有 db_admin ,而我只想授予他们 db_creator ,但每当有人创建数据库,其他用户也应该有权访问这个数据库。

我尝试过创建SQL触发器:

USE master
GO
CREATE TRIGGER trg_DDL_CreateDatabase
ON ALL SERVER
FOR CREATE_DATABASE
AS

DECLARE @databaseName varchar(max)
SET @databaseName = (SELECT EVENTDATA().value('(/EVENT_INSTANCE/DatabaseName)[1]', 'VARCHAR(255)'))

EXEC ('USE [' + @databaseName + ']' )

IF IS_MEMBER ('DOMAIN\GROUP') = 1
EXEC sp_addrolemember N'db_owner', N'DOMAIN\SOMEGROUP'
ELSE
EXEC sp_addrolemember N'db_owner', N'DOMAIN\SOMEOTHERGROUP'

GO

由于我在触发器中无法使用USE语句,我尝试使用EXEC ('USE [' + @databaseName + ']' )方法 - 但它也不起作用。

有什么建议吗?

编辑:如果我可以根据群组成员资格授予不同的权限,那就太棒了。例如,用户是组A的成员,然后将A添加到db_owner,如果B,则添加B,C和E等。

1 个答案:

答案 0 :(得分:3)

每个数据库都被创建为[model]的副本。您在[model]中应用的任何用户,组和授权都将自动复制到任何新创建的数据库中。请注意,这不适用于附加的数据库。

如果您想通过DDL触发器执行此操作,则需要为整个批处理使用动态sql:

CREATE TRIGGER trg_DDL_CreateDatabase
ON ALL SERVER
FOR CREATE_DATABASE
AS
DECLARE @databaseName sysname;
SET @databaseName = (SELECT EVENTDATA().value('(/EVENT_INSTANCE/DatabaseName)[1]', 'sysname'));
declare @sql nvarchar(max);
set @sql = N'USE ' + quotename(@databaseName) + N';
IF IS_MEMBER (''DOMAIN\GROUP'') = 1
EXEC sp_addrolemember N''db_owner'', N''DOMAIN\SOMEGROUP''
ELSE
EXEC sp_addrolemember N''db_owner'', N''DOMAIN\SOMEOTHERGROUP'';';
exec sp_executesql @sql;

好的做法是使用QUOTENAME()来正确转义名称。在提取(xml方法)和存储(变量类型)中使用sysname作为数据库名称类型。因为你的代码很容易被db_creator利用来通过SQL注入将自己提升为系统管理员(创建一个合适的数据库名称并将其打造)。