存储过程作为所有者执行关闭数据库连接不起作用

2 sql-server permissions sql-server-2012 connections impersonation

我创建了一个存储过程,允许用户在 QA 环境中关闭所有数据库连接。我是 SA 并创建了程序。

当我修改 SP 时,在没有“以所有者身份执行”的情况下运行它,我得到了结果。当我添加“以所有者身份执行”时,我没有收到任何结果。

试图理解为什么。

create procedure [dbo].[DatabaseConnectionClose]
    @DatabaseName varchar(255)
with execute as owner
as


DECLARE @kill varchar(8000) = '';  
SELECT @kill = @kill + 'kill ' + CONVERT(varchar(5), session_id) + ';'  
FROM sys.dm_exec_sessions
WHERE database_id  = db_id(@DatabaseName)

select @kill as CloseConnectionScript

EXEC(@kill);
Run Code Online (Sandbox Code Playgroud)

Sol*_*zky 8

使用语句的EXECUTE AS子句CREATE {module_type}是模拟,但仅限于数据库级别。所有者是“dbo”(至少在这种情况下),但这只是一个用户;数据库级主体。该KILL命令需要实例级权限。默认情况下,当使用数据库级模拟(EXECUTE AS子句 EXECUTE AS USER语句)时,进程被隔离到当前数据库,即使该用户映射到具有适当权限的登录(通过具有相同的 SID)。由于此限制,不允许进程到达实例以检查实例级别的权限。

要正确执行此操作:

  1. 摆脱 EXECUTE AS
  2. 使用模块签名来实现:

    在不授予任何人的情况下安全轻松地使用高级权限:服务器级(我的博客文章;外部,但有更好的解释)

    我需要为用户提供哪些最低权限才能检查 SQL Server 代理服务的状态?(我的答案之一,在 DBA.SE 上)

    您需要授予基于证书的登录的唯一权限是:(ALTER ANY CONNECTION根据KILL的文档)

有关模块签名的更多信息,请访问:模块签名信息


此外,除了由阿龙贝特朗在关于这个问题的意见提出的非常好的一点,你必须要小心不要杀会议合法程序,如SQL Server代理,等你应该至少过滤上program_name的柱sys.dm_exec_sessions,如果不是login_name(也可能是其他人)。

但是,如果ALTER DATABASE [{db_name}] SET...最终成为继续进行的方式,则使用以下帖子作为指南,因为在这种情况下您不会关心实例级别的权限:

安全轻松地使用高级权限,无需授予任何人:数据库级别