SQL Server REVOKE 需要 CASCADE

ste*_*osz 2 sql-server permissions

我有以下图表:

  • B 授予对 D 的选择,D 授予对 E 的选择,E 授予对 G 的选择。
  • B 已授予带有授予选项的选择,并且已授予带有授予选项的选择 D。
  • D 已授予带有授予选项的选择,并且已授予带有授予选项的选择 E。
  • E 已授予带有授予选项的选择,并且已授予带有授予选项的选择 G。

当我尝试撤销 D 上的 GRANT SELECT 时,出现错误,需要使用 CASCADE。

代码:

EXECUTE AS USER = 'userB';
GO
REVOKE GRANT OPTION FOR SELECT ON EMP FROM userD;
GO
REVERT;
Run Code Online (Sandbox Code Playgroud)

错误:

要撤销或拒绝可授予的权限,请指定 CASCADE 选项。

我需要的是删除 GRANT SELECT 而不删除 E 和 G 中的 GRANT SELECT。

Han*_*non 5

当您使用该子句向用户授予权限WITH GRANT OPTION,然后撤销该权限时,SQL Server 将阻止撤销,除非您将该CASCADE选项显式添加到REVOKE ...语句中。

WITH GRANT OPTION这可以防止您向用户授予权限,而该用户随后又向您不知情的其他人授予权限的安全风险。然后您撤销该用户的权利,但损害已经造成。当您尝试撤销已使用 grant 选项分配的权限时,会引发此错误消息,除非您使用以下CASCADE选项:

消息 4611,第 16 级,状态 1,第 44 行

要撤销或拒绝可授予的权限,请指定 CASCADE 选项。

为了撤销使用该WITH GRANT OPTION子句授予的权限,您必须使用该选项撤销该权限CASCADE。这还会删除已由 . 的用户授予权限的所有用户的已撤销权限GRANT OPTION。如果您希望这些其他用户保留该用户通过 授予的权限GRANT OPTION,则必须手动将这些权限显式分配给这些其他用户。

下面的代码是一个简单的重现,显示了症状以及如何处理它。

首先,创建一个我们可以为其分配权限的对象:

IF OBJECT_ID('dbo.TestSelect') IS NULL
CREATE TABLE dbo.TestSelect
(
    t INT
);
Run Code Online (Sandbox Code Playgroud)

创建三个用户:

IF NOT EXISTS (
    SELECT 1 
    FROM sys.database_principals dp 
    WHERE dp.name = 'u1')
CREATE USER u1 WITHOUT LOGIN;

IF NOT EXISTS (
    SELECT 1 
    FROM sys.database_principals dp 
    WHERE dp.name = 'u2')
CREATE USER u2 WITHOUT LOGIN;

IF NOT EXISTS (
    SELECT 1 
    FROM sys.database_principals dp 
    WHERE dp.name = 'u3')
CREATE USER u3 WITHOUT LOGIN;
Run Code Online (Sandbox Code Playgroud)

授予SELECT WITH GRANT OPTION用户u1

GRANT SELECT ON dbo.TestSelect TO u1 WITH GRANT OPTION;
Run Code Online (Sandbox Code Playgroud)

授予SELECT WITH GRANT OPTION用户u2作为用户 'u1' :

EXECUTE AS USER = 'u1';

GRANT SELECT ON dbo.TestSelect TO u2 WITH GRANT OPTION;

REVERT
Run Code Online (Sandbox Code Playgroud)

授予SELECT WITH GRANT OPTION用户u3作为用户 'u2' :

EXECUTE AS USER = 'u2';

GRANT SELECT ON dbo.TestSelect TO u3 WITH GRANT OPTION;

REVERT
Run Code Online (Sandbox Code Playgroud)

确保我们以初始用户身份运行(在我的例子中为 dbo)

SELECT USER_NAME();
Run Code Online (Sandbox Code Playgroud)

尝试在不使用该选项的情况下删除SELECT用户的权限,这将失败:u1CASCADE

REVOKE SELECT ON dbo.TestSelect FROM u1;
--Msg 4611, Level 16, State 1, Line 44
--To revoke or deny grantable privileges, specify the CASCADE option.
Run Code Online (Sandbox Code Playgroud)

添加该CASCADE选项,该选项有效:

REVOKE SELECT ON dbo.TestSelect FROM u1 CASCADE;
Run Code Online (Sandbox Code Playgroud)

查看其他用户是否有权访问测试表(因为我们已使用该CASCADE选项撤消了访问权限,所以他们没有权限):

EXECUTE AS USER = 'u2';

SELECT *
FROM dbo.TestSelect;
--Msg 229, Level 14, State 5, Line 51
--The SELECT permission was denied on the object 'TestSelect', database 'Test', schema 'dbo'.
Run Code Online (Sandbox Code Playgroud)

恢复到“dbo”用户,这样我们就可以将SELECT测试对象授予其余用户:

REVERT -- back to 'dbo'

GRANT SELECT ON dbo.TestSelect TO U2;
GRANT SELECT ON dbo.TestSelect TO U3;
Run Code Online (Sandbox Code Playgroud)

确认其他用户有权访问测试对象:

EXECUTE AS USER = 'u2';

SELECT *
FROM dbo.TestSelect;

REVERT -- back to 'dbo'

EXECUTE AS USER = 'u3';

SELECT *
FROM dbo.TestSelect;

REVERT -- back to 'dbo'
Run Code Online (Sandbox Code Playgroud)

清理测试对象和用户:

DROP TABLE dbo.TestSelect
DROP USER u3;
DROP USER u2;
DROP USER u1;
Run Code Online (Sandbox Code Playgroud)