MsSQL Server 2016行级别访问权限控制

2024-04-13 06:48

本文主要是介绍MsSQL Server 2016行级别访问权限控制,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

背景

假如我们有关键数据存储在一个表里面,比如人员表中包含员工、部门和薪水信息。只允许用户访问各自部门的信息,但是不能访问其他部门。一般我们都是在程序端实现这个功能,而在sqlserver2016以后也可以直接在数据库端实现这个功能。

解决

安全已经是一个数据方面的核心问题,每一代的MS数据库都有关于安全方面的新功能,那么在Sql Server 2016,也有很多这方面的升级,比如‘Row Level Security’, ‘Always Encrypted’, ‘Dynamic Data Masking’, 和‘Enhancement of Transparent Data Encryption’ 等等都会起到安全方面的作用。本篇我将介绍关于Row Level Security (RLS--行级别安全), 能够控制表中行的访问权限。RLS 能使我们根据执行查询人的属性来控制基础数据,从而帮助我们容易地为不同用户提透明的访问数据。行级安全性使客户能够根据执行查询的用户的特性控制数据库中的行。

为了实现RLS我们需要准备下面三个方面:

  1. 谓词函数
  2. 安全谓词
  3. 安全策略

逐一描述上面三个方面

谓词函数

谓词函数是一个内置的表值函数,用于检查用户执行的查询访问数据是否基于其逻辑定义。这个函数返回一个1来表示用户可以访问。

安全谓词

安全谓词就是将谓词函数绑定到表里面,RLS提供了两种安全谓词:过滤谓词和阻止谓词。过滤谓词就是在使用SELECT, UPDATE, 和 DELETE语句查询数据时只是过滤数据但是不会报错。而阻止谓词就是在使用违反谓词逻辑的数据时,显示地报错并且阻止用户使用 AFTER INSERT, AFTER UPDATE, BEFORE UPDATE, BEFORE DELETE 等操作。

安全策略

安全策略对象专门为行级别安全创建,分组所有涉及谓词函数的安全谓词。

实例

实例中我们创建一个Person表和测试数据,最后我们让不懂得用户访问各自部门的信息,代码如下:

复制代码

Create table dbo.Person(PersonId INT IDENTITY(1,1),PersonName varchar(100),Department varchar(100),Salary INT,User_Access varchar(50))GOINSERT INTO Person (PersonName, Department, Salary, User_Access)SELECT 'Ankit', 'CS', 40000, 'User_CS'UNION ALLSELECT 'Sachin', 'EC', 20000, 'User_EC'UNION ALLSELECT 'Kapil', 'CS', 30000, 'User_CS'UNION ALLSELECT 'Ishant', 'IT', 50000, 'User_IT'UNION ALLSELECT 'Aditya', 'EC', 45000, 'User_EC'UNION ALLSELECT 'Sunny', 'IT', 60000, 'User_IT'UNION ALLSELECT 'Rohit', 'CS', 55000, 'User_CS'GO

复制代码

 

 

此时表已经被创建,并且插入了测试数据,执行下面语句检索有是有的记录:

SELECT * FROM Person

clip_image001

正如所示,目前有三个部门department(CS,EC,IT),并且User_Access列表示各自的用户组。让我们创建三个测试用户数据的账户语句如下:

复制代码

--For CS departmentCREATE USER User_CS WITHOUT LOGIN--For EC departmentCREATE USER User_EC WITHOUT LOGIN-- For IT DepartmentCREATE USER User_IT WITHOUT LOGIN

复制代码

 

在创建了用户组以后,授权读取权限给上面是哪个新建的用户,执行语句如下:

复制代码

---授予select权限给所有的用户GRANT SELECT ON Person TO User_CSGRANT SELECT ON Person TO User_ECGRANT SELECT ON Person TO User_IT

复制代码

 

现在我们创建一个谓词函数,该函数是对于查询用户是不可见的。

复制代码

----Create functionCREATE FUNCTION dbo.PersonPredicate( @User_Access AS varchar(50) )RETURNS TABLEWITH SCHEMABINDINGASRETURN SELECT 1 AS AccessRightWHERE @User_Access = USER_NAME()GO

复制代码

 

 

这个函数是只返回行,如果正在执行查询的用户的名字与User_Access 列匹配,那么用户允许访问指定的行。在创建该函数后,还需要创建一个安全策略,使用上面的谓词函数PersonPredicate来对表进行过滤逻辑的绑定,脚本如下:

复制代码

--安全策略CREATE SECURITY POLICY PersonSecurityPolicyADD FILTER PREDICATE dbo.PersonPredicate(User_Access) ON dbo.PersonWITH (STATE = ON)

复制代码

 

 

State(状态)为ON才能是策略生效,如果打算关闭策略,你可以改变状态为OFF。

再来看一下查询结果:

clip_image002

这次查询没有返回任何行,这意味着谓词函数的定义和策略的创建后,用户查询需要具有相应权限才能返回行,接下来使用不同用户来查询这个数据,首先,我们用用户User_CS来查询一下结果:

EXECUTE AS USER = 'User_CS'SELECT * FROM dbo.PersonREVERT

 

 

正如所示,我们看到只有三行数据数据该用户,User_CS,已经检索出来。因此,过滤函数将其他不属于该用户组的数据过滤了。

实际上这个查询执行的过程就是数据库内部调用谓词函数,如下所示:

SELECT * FROM dbo.Person

WHERE User_Name() = 'User_CS'

其他两组用户的查询结果是相似的这里就不一一演示了。

因此,我们能看到执行查询根据用的不同得到只属于指定用户组的指定数据。这就是我们要达成的目的。

到目前为止,我们已经演示了过滤谓词,接下来我们演示一下如何阻止谓词。执行如下语句来授权DML操作权限给用户。

复制代码

--授权DML 权限GRANT INSERT, UPDATE, DELETE ON Dbo.Person TO User_CSGRANT INSERT, UPDATE, DELETE ON Dbo.Person TO User_ECGRANT 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.PersonREVERT

 

奇怪,新插入行并没有插入到该用户组'User_IT'中。而是出现在了'User_CS' 的用户组数据中。

复制代码

--插入数据出现在了不同的用户组EXECUTE AS USER = 'User_CS'SELECT * FROM dbo.PersonREVERT

复制代码

 

clip_image005

通过上面的例子我们发现,过滤谓词不不会阻止用户插入数据,因此没有错误,这是因为没有在安全策略中定义阻止谓词。让我们加入阻止谓词来显示报错,有四个阻止谓词AFTER INSERT, AFTER UPDATE, BEFORE UPDATE, 和 BEFORE DELETE可以使用。我们这里测试使用AFTER INSERT 谓词。这个谓词阻止用户插入记录到没有权限查看的数据用户组。

添加谓词阻止的安全策略,代码如下:

复制代码

--添加阻止谓词ALTER SECURITY POLICY PersonSecurityPolicyADD 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

复制代码

 

1

 

擦,果然这次错误出提示出现了,阻止了不同权限用户的插入。因此我们能说通过添加阻止谓词,未授权用户的DML操作被限制了。

注意:在例子中每个部门只有一个用户组成。如果在一个部门包含多个用户的情况下,我们需要创建分支登录为每个用户都分配需要的权限,因为谓词函数应用于用户基础并且安全策略取决于谓词函数。

 

行级别安全的限制

这里有几个行级别安全的限制:

  1. 谓词函数一定要带有WITH SCHEMABINDING关键词,如果函数没有该关键字则绑定安全策略时会抛出异常。
  2. 在实施了行级别安全的表上不能创建索引视图。
  3. 内存数据表不支持
  4. 全文索引不支持

总结

带有行级别安全功能的SQLServer2016,我们可以不通过应用程序级别的代码修改来实现数据记录的权限控制。行级别安全通过使用谓词函数和安全策略实现,不需要修改各种DML代码,伴随着现有代码即可实现。

这篇关于MsSQL Server 2016行级别访问权限控制的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/899420

相关文章

SQL Server配置管理器无法打开的四种解决方法

《SQLServer配置管理器无法打开的四种解决方法》本文总结了SQLServer配置管理器无法打开的四种解决方法,文中通过图文示例介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的... 目录方法一:桌面图标进入方法二:运行窗口进入检查版本号对照表php方法三:查找文件路径方法四:检查 S

MySQL中的InnoDB单表访问过程

《MySQL中的InnoDB单表访问过程》:本文主要介绍MySQL中的InnoDB单表访问过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、背景2、环境3、访问类型【1】const【2】ref【3】ref_or_null【4】range【5】index【6】

前端如何通过nginx访问本地端口

《前端如何通过nginx访问本地端口》:本文主要介绍前端如何通过nginx访问本地端口的问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、nginx安装1、下载(1)下载地址(2)系统选择(3)版本选择2、安装部署(1)解压(2)配置文件修改(3)启动(4)

Spring如何使用注解@DependsOn控制Bean加载顺序

《Spring如何使用注解@DependsOn控制Bean加载顺序》:本文主要介绍Spring如何使用注解@DependsOn控制Bean加载顺序,具有很好的参考价值,希望对大家有所帮助,如有错误... 目录1.javascript 前言2. 代码实现总结1. 前言默认情况下,Spring加载Bean的顺

基于Python开发Windows屏幕控制工具

《基于Python开发Windows屏幕控制工具》在数字化办公时代,屏幕管理已成为提升工作效率和保护眼睛健康的重要环节,本文将分享一个基于Python和PySide6开发的Windows屏幕控制工具,... 目录概述功能亮点界面展示实现步骤详解1. 环境准备2. 亮度控制模块3. 息屏功能实现4. 息屏时间

PostgreSQL 默认隔离级别的设置

《PostgreSQL默认隔离级别的设置》PostgreSQL的默认事务隔离级别是读已提交,这是其事务处理系统的基础行为模式,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价... 目录一 默认隔离级别概述1.1 默认设置1.2 各版本一致性二 读已提交的特性2.1 行为特征2.2

SQL Server修改数据库名及物理数据文件名操作步骤

《SQLServer修改数据库名及物理数据文件名操作步骤》在SQLServer中重命名数据库是一个常见的操作,但需要确保用户具有足够的权限来执行此操作,:本文主要介绍SQLServer修改数据... 目录一、背景介绍二、操作步骤2.1 设置为单用户模式(断开连接)2.2 修改数据库名称2.3 查找逻辑文件名

SQL Server数据库死锁处理超详细攻略

《SQLServer数据库死锁处理超详细攻略》SQLServer作为主流数据库管理系统,在高并发场景下可能面临死锁问题,影响系统性能和稳定性,这篇文章主要给大家介绍了关于SQLServer数据库死... 目录一、引言二、查询 Sqlserver 中造成死锁的 SPID三、用内置函数查询执行信息1. sp_w

Python远程控制MySQL的完整指南

《Python远程控制MySQL的完整指南》MySQL是最流行的关系型数据库之一,Python通过多种方式可以与MySQL进行交互,下面小编就为大家详细介绍一下Python操作MySQL的常用方法和最... 目录1. 准备工作2. 连接mysql数据库使用mysql-connector使用PyMySQL3.

Linux中修改Apache HTTP Server(httpd)默认端口的完整指南

《Linux中修改ApacheHTTPServer(httpd)默认端口的完整指南》ApacheHTTPServer(简称httpd)是Linux系统中最常用的Web服务器之一,本文将详细介绍如何... 目录一、修改 httpd 默认端口的步骤1. 查找 httpd 配置文件路径2. 编辑配置文件3. 保存