时间:2021-07-01 10:21:17 帮助过:5人阅读
此时表已经被创建,并且插入了测试数据,执行下面语句检索有是有的记录:
SELECT * FROM Person
正如所示,目前有三个部门department(CS,EC,IT),并且User_Access列表示各自的用户组。让我们创建三个测试用户数据的账户语句如下:
--For CS department CREATE USER User_CS WITHOUT LOGIN --For EC department CREATE USER User_EC WITHOUT LOGIN -- For IT Department CREATE USER User_IT WITHOUT LOGIN
在创建了用户组以后,授权读取权限给上面是哪个新建的用户,执行语句如下:
---授予select权限给所有的用户 GRANT SELECT ON Person TO User_CS GRANT SELECT ON Person TO User_EC GRANT SELECT ON Person TO User_IT
现在我们创建一个谓词函数,该函数是对于查询用户是不可见的。
----Create function CREATE FUNCTION dbo.PersonPredicate ( @User_Access AS varchar(50) ) RETURNS TABLE WITH SCHEMABINDING AS RETURN SELECT 1 AS AccessRight WHERE @User_Access = USER_NAME() GO
这个函数是只返回行,如果正在执行查询的用户的名字与User_Access 列匹配,那么用户允许访问指定的行。在创建该函数后,还需要创建一个安全策略,使用上面的谓词函数PersonPredicate来对表进行过滤逻辑的绑定,脚本如下:
--安全策略 CREATE SECURITY POLICY PersonSecurityPolicy ADD FILTER PREDICATE dbo.PersonPredicate(User_Access) ON dbo.Person WITH (STATE = ON)
State(状态)为ON才能是策略生效,如果打算关闭策略,你可以改变状态为OFF。
再来看一下查询结果:
这次查询没有返回任何行,这意味着谓词函数的定义和策略的创建后,用户查询需要具有相应权限才能返回行,接下来使用不同用户来查询这个数据,首先,我们用用户User_CS来查询一下结果:
EXECUTE AS USER = ‘User_CS‘ SELECT * FROM dbo.Person REVERT
正如所示,我们看到只有三行数据数据该用户,User_CS,已经检索出来。因此,过滤函数将其他不属于该用户组的数据过滤了。
实际上这个查询执行的过程就是数据库内部调用谓词函数,如下所示:
SELECT * FROM dbo.Person
WHERE User_Name() = ‘User_CS‘
其他两组用户的查询结果是相似的这里就不一一演示了。
因此,我们能看到执行查询根据用的不同得到只属于指定用户组的指定数据。这就是我们要达成的目的。
到目前为止,我们已经演示了过滤谓词,接下来我们演示一下如何阻止谓词。执行如下语句来授权DML操作权限给用户。
--授权DML 权限 GRANT INSERT, UPDATE, DELETE ON Dbo.Person TO User_CS GRANT INSERT, UPDATE, DELETE ON Dbo.Person TO User_EC GRANT INSERT, UPDATE, DELETE ON Dbo.Person TO User_IT
我们用用户User_IT执行插入语句,并且插入用户组为UserCS的,语句如下:
EXECUTE AS USER = ‘User_IT‘ INSERT INTO Person (PersonName, Department, Salary, User_Access) SELECT ‘Soniya‘, ‘CS‘, 35000, ‘User_CS‘ REVERT
but,竟然没有报错,插入成功了。
让我们在检查一下用户数据插入的情况:
EXECUTE AS USER = ‘User_IT‘ SELECT * FROM dbo.Person REVERT
奇怪,新插入行并没有插入到该用户组‘User_IT‘中。而是出现在了‘User_CS‘ 的用户组数据中。
--插入数据出现在了不同的用户组 EXECUTE AS USER = ‘User_CS‘ SELECT * FROM dbo.Person REVERT
通过上面的例子我们发现,过滤谓词不不会阻止用户插入数据,因此没有错误,这是因为没有在安全策略中定义阻止谓词。让我们加入阻止谓词来显示报错,有四个阻止谓词AFTER INSERT, AFTER UPDATE, BEFORE UPDATE, 和 BEFORE DELETE可以使用。我们这里测试使用AFTER INSERT 谓词。这个谓词阻止用户插入记录到没有权限查看的数据用户组。
添加谓词阻止的安全策略,代码如下:
--添加阻止谓词 ALTER SECURITY POLICY PersonSecurityPolicy ADD BLOCK PREDICATE dbo.PersonPredicate(User_Access) ON dbo.Person AFTER INSERT
现在我们用之前类似代码再试一下,是否可以插入数据:
EXECUTE AS USER = ‘User_CS‘ INSERT INTO Person (PersonName, Department, Salary, User_Access) SELECT ‘Sumit‘, ‘IT‘, 35000, ‘User_IT‘ REVERT
擦,果然这次错误出提示出现了,阻止了不同权限用户的插入。因此我们能说通过添加阻止谓词,未授权用户的DML操作被限制了。
注意:在例子中每个部门只有一个用户组成。如果在一个部门包含多个用户的情况下,我们需要创建分支登录为每个用户都分配需要的权限,因为谓词函数应用于用户基础并且安全策略取决于谓词函数。
这里有几个行级别安全的限制:
总结
带有行级别安全功能的SQLServer2016,我们可以不通过应用程序级别的代码修改来实现数据记录的权限控制。行级别安全通过使用谓词函数和安全策略实现,不需要修改各种DML代码,伴随着现有代码即可实现。
SQL Server 2016 行级别权限控制
标签:t权限 一个用户 data 插入 display -- 匹配 个数 nio