接上文: SQL Server 安全篇——数据层面安全性(2)——所有权链接( Ownership Chaining)
模拟是指在不同安全主体的上下文下执行T-SQL语句或代码模块的做法。用来最小化权限授予和授予权限的用户数,但是不影响执行时提升到所需的权限。实际上,在会话或模块的执行期间,模拟起到了用户或登录名切换的过程。也可以不严谨地认为,发起模拟的用户A借用B的身份执行了B有权限但A没权限做的事。
在SQL Server中,可以使用EXECUTE AS子句来实现模拟功能。EXECUTE AS可以位于存储过、函数、DML触发器的头部。也可以用于会话过程切换安全上下文。下表是EXECUTE AS可用场景:
用处 | 上下文规范(Context Specification) |
Session(会话) |
|
存储过程、函数、DML触发器 |
|
库级别DDL触发器 |
|
服务器级别DDL触发器 |
|
Queues(队列) |
|
上下文规范(Context Specification)说明
- CALLER:意味着代码运行在原始上下文,是除队列之外的默认行为。
- SELF:代码在创建或最后更改模块的主体的上下文下执行。
- OWNER:代码运行在安全主体的拥有者上下文。
- USER:以数据库特定用户运行代码。
- LOGIN:以特定登录名来运行代码。
下面来演示一下,首先创建一个登录名George:
USE master GO CREATE LOGIN George WITH PASSWORD='强密码', DEFAULT_DATABASE=master, CHECK_EXPIRATION=OFF, CHECK_POLICY=ON ; GO然后在演示库创建一个用户,关联这个登录名:
USE AdventureWorks2016 GO CREATE USER George FOR LOGIN George
然后调用不带参数的SUSER_SNAME()函数返回当前安全上下文的登录名(注意这里不能是“组”或者“绝色”,必须是单一账号):
USE AdventureWorks2016 GO --以当前上下文运行 SELECT SUSER_SNAME() ; --转换当前上下文为George用户 EXECUTE AS USER = 'George' ; --再次查询 SELECT SUSER_NAME() ;
结果如图:
第一个查询运行在我自己的登录名的安全上下文中,当执行完EXECUTE AS语句之后,上下文切换成George,但是注意除非你关掉这个界面,不然需要使用REVERT命令来恢复上下文,否则将一直以George的上下文来运行。
准确来说,在下面情况发生之前,切换后的上下文一直有效:
- 运行另一个Execute AS语句
- 运行REVERT语句
- 删除会话(比如SSMS关闭查询窗口)
- 存储过程或触发器中的命令执行了退出操作。
注意:对于即席查询(ad hoc SQL)的EXECUTE AS子句,必须在安全上下文中具有模拟权限,否则使用EXECUTE AS也会报错。另外,非包含数据库或SQL DB(Azure上)之外的模拟,其执行返回限制于服务器级别。
最佳实践:
首先当然还是要维持最低所需权限。比如只需要DB级别的就不要给Server级别的权限。当需要在一个过程中切换多次登录时(不建议),要保持原始登录的识别,以免后续忘记切回去,这个原始登录可以通过ORIGINAL_LOGIN函数来获取。
注:本文内容来自互联网,旨在为开发者提供分享、交流的平台。如有涉及文章版权等事宜,请你联系站长进行处理。