内容简介:Row Level Security,行级安全性,简称RLS,是从SQL Server 2016引入。相对于过去,仅能对对象或语句进行权限控制从而对表的全部数据行实现权限管理而言,现在可以使用RLS针对特定的行进行授权。当然,视图也是可以做到的,但是RLS可能是更好的选择,因为RLS还实现了一些额外的功能用于在执行前或执行后进行一些阻止操作。在介绍内部知识之前,先做一个演示,可能会更加深刻。但是在此之前先下载另外一个新的演示数据库WideWorldImporters ,下载方法可以参考前面的文章:这个角色映
Row Level Security,行级安全性,简称RLS,是从SQL Server 2016引入。相对于过去,仅能对对象或语句进行权限控制从而对表的全部数据行实现权限管理而言,现在可以使用RLS针对特定的行进行授权。当然,视图也是可以做到的,但是RLS可能是更好的选择,因为RLS还实现了一些额外的功能用于在执行前或执行后进行一些阻止操作。
RLS演示
在介绍内部知识之前,先做一个演示,可能会更加深刻。但是在此之前先下载另外一个新的演示数据库WideWorldImporters ,下载方法可以参考前面的文章: SQL Server On Linux(3)——SQL Server 2019 For Linux 下载并部署示例数据库
创建用于RLS操作的 SQL 登录账号
USE master GO IF NOT EXISTS (SELECT 1 FROM sys.server_principals WHERE name = N'RLSTest') BEGIN CREATE LOGIN RLSTest WITH PASSWORD = N'abc.123', CHECK_POLICY = OFF, CHECK_EXPIRATION = OFF, DEFAULT_DATABASE = WideWorldImporters; END GO
创建映射到登录名的用户并添加到已存在的角色中
这个角色映射到销售区域(sales territories)
USE WideWorldImporters; GO DROP USER IF EXISTS RLSTest GO CREATE USER RLSTest FOR LOGIN RLSTest GO ALTER ROLE [Great Lakes Sales] ADD MEMBER RLSTest --Great Lakes Sales已存在于该数据库中 GO
创建安全策略
使用RLS需要创建一个SQL Server函数,用于确定查询可以访问哪些数据行。所以需要创建一个安全策略映射到这个函数。
-- 删除已存在的安全策略和函数 -- DROP SECURITY POLICY IF EXISTS [Application].FilterCustomersBySalesTerritoryRole GO DROP FUNCTION IF EXISTS [Application].DetermineCustomerAccess GO -- 创建用于RLS的函数 -- CREATE FUNCTION [Application].DetermineCustomerAccess(@CityID int) RETURNS TABLE WITH SCHEMABINDING AS RETURN (SELECT 1 AS AccessResult WHERE IS_ROLEMEMBER(N'db_owner') <> 0 OR IS_ROLEMEMBER((SELECT sp.SalesTerritory FROM [Application].Cities AS c INNER JOIN [Application].StateProvinces AS sp ON c.StateProvinceID = sp.StateProvinceID WHERE c.CityID = @CityID) + N' Sales') <> 0 ) GO -- 创建使用RLS函数的安全策略 -- CREATE SECURITY POLICY [Application].FilterCustomersBySalesTerritoryRole ADD FILTER PREDICATE [Application].DetermineCustomerAccess (DeliveryCityID) ON Sales.Customers GO
现在解释一下这个函数,它获取CityID的值,然后从Cities表和StateProvinces表中获取city的SalesTerritory名。然后把’Sales’追加到名字的末尾。这就任何在GreatLakes区域的CityID都会返回到GreatLakesSales中。
安全策略从[Sales].[Customers]表中返回DeliveryCityID。通过这个策略,如果以RLSTest用户登录并查询Customers表,那么只会返回符合规则的数据。下面就来测试一下。
测试效果
首先使用sa来测试:
SELECT COUNT(*) FROM Sales.Customers;
然后我们以RLSTest身份来执行,这里并没有修改任何查询语句。
GRANT SELECT, UPDATE ON Sales.Customers TO [Great Lakes Sales]; GO -- 以 RLSTest身份执行 EXECUTE AS USER = 'RLSTest' GO SELECT COUNT(*) FROM Sales.Customers; GO --收回权限 REVERT GO
上图可以看到,用不同的用户执行相同的语句返回了不一样的结果,证明函数起效了。下面来做专业一点的介绍。
RLS技术说明
在过去,为了实现不同角色的用户访问不同的数据,即使是同一个表,也要进行多个视图控制或者架构等改变,这个操作需要从前端到后端一并实现,变更起来也很不方便。从SQL 2016开始,引入了RLS,相对于过去,RLS提供了相当简化的实现方式。
RLS提供了基于数据行的读写访问控制,并且最小化架构、应用程序或者查询语句的变更。
RLS概念
RLS有三个核心概念:
- 谓词函数:Predicate function,用于实现访问控制逻辑的表值内联函数(inline table-valued funcation)
- 安全谓词:Security predicate,把谓词函数应用于表。
- 安全策略:Security policy,安全谓词的集合。
回看前面的谓词函数,需要注意的是函数要使用SCHEMABINDING,以免底层表的变更带来影响,但是仅仅创建函数是不够的,需要某个方式把函数应用到表上,这个时候就引出了安全策略。安全策略是安全谓词的集合,上面例子中仅对一个表进行操作,但是实际上可以对多个表进行操作,比如可以写成:
CREATE SECURITY POLICY AccountAndRepPolicy ADD FILTER PREDICATE dbo.LimitAccountAccess(RepID) ON dbo.AccountReps, ADD FILTER PREDICATE dbo.LimitAccountAccess(RepID) ON dbo.Accounts WITH (STATE = ON);
这个安全策略把谓词函数dbo.LimitAccountAccess()应用到两个表中。通过ADD FILTER PREDICATE来实现。
阻止谓词
下面来介绍一下RLS对“写”操作的行为,阻止谓词显式阻止违反该谓词的写入操作,包含AFTER INSERT、AFTER UPDATE、BEFORE UPDATE、BEFORE DELETE。
- AFTER INSERT 和 AFTER UPDATE 谓词可以防止用户将行更新为违反该谓词的值
- BEFORE UPDATE 谓词可以防止用户更新当前违反该谓词的行
- BEFORE DELETE 谓词可以阻止删除操作
实现这种阻止操作,需要在安全策略中使用BLOCK谓词,在FILTER谓词过滤掉不可见的数据之后,再进行阻止,因为FILTER并不阻止数据插入。可以创建另外一个谓词函数,然后如下面添加ADD BLOCK PREDICATE来实现即可。这里就不演示了。
CREATE SECURITY POLICY [Application].FilterCustomersBySalesTerritoryRole ADD FILTER PREDICATE [Application].DetermineCustomerAccess (DeliveryCityID) ON Sales.Customers ADD BLOCK PREDICATE 阻止函数 ON Sales.Customers GO
RLS是其中一个官方和SQL Server专家都推荐使用的安全功能,它类似触发器,也类似视图,RLS的其中一个亮点是简化了开发的工作量和复杂度。由于其功能强大,很多细节不打算在这里讲解,在后续再做一些案例演示,这篇的主要目的是引出这个功能,之所以没有做更多演示的原因是官方文档: 行级安全性 还是比较难度懂,我也在想如何能够在严谨的前提下做到易懂,所以在没做到这个程度之前先不引入得太深。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Agile Web Application Development with Yii 1.1 and PHP5
Jeffrey Winesett / Packt Publishing / 2010-08-27
In order to understand the framework in the context of a real-world application, we need to build something that will more closely resemble the types of applications web developers actually have to bu......一起来看看 《Agile Web Application Development with Yii 1.1 and PHP5》 这本书的介绍吧!