EXECUTE AS (Transact-SQL)

applies to:SQL ServerAzure SQL 数据库Azure SQL 托管实例Azure Synapse Analytics

设置会话的执行上下文。

默认情况下,会话在用户登录时开始,在用户注销时结束。 会话过程中的所有操作都受限于对该用户进行的权限检查。 当运行语 EXECUTE AS 句时,会话的执行上下文会切换到指定的登录名或用户名。 上下文切换后,权限会被与该账户的登录和用户安全令牌进行核对,而不是调用语 EXECUTE AS 句的人。 实际上,在会话或模块的执行期间模拟了用户或登录帐户,或显式恢复了上下文切换。

Transact-SQL语法约定

语法

{ EXEC | EXECUTE } AS <context_specification>  
[;]  
  
<context_specification>::=  
{ LOGIN | USER } = 'name'  
    [ WITH { NO REVERT | COOKIE INTO @varbinary_variable } ]   
| CALLER  

参数

LOGIN
应用到:SQL Server 2008(10.0.x)及更高版本。

指定要模拟的执行上下文是一个登录名。 模拟范围处于服务器级别。

注意

此选项在包含的数据库、Azure SQL 数据库或Azure Synapse Analytics中不可用。

USER
指定要模拟的上下文是当前数据库中的用户。 模拟范围只限于当前数据库。 对数据库用户的上下文切换不会继承该用户的服务器级别权限。

重要

当到数据库用户的上下文切换处于活动状态时,任何对数据库以外资源的访问尝试都将导致语句失败。 这包括 USE database 语句、分布式查询以及引用其他数据库(使用由三或四部分构成的标识符)的查询。

'name' 是有效的用户或登录名。 name 必须是 sysadmin 固定服务器角色的成员,或者分别作为 sys.database_principalssys.server_principals 中的主体而存在。

可以将 name 指定为局部变量。

name 必须是单一实例帐户,而不能是组、角色、证书、密钥或内置帐户,如 NT AUTHORITY\LocalService、NT AUTHORITY\NetworkService 或 NT AUTHORITY\LocalSystem。

有关详细信息,请参阅本主题后面的指定用户名或登录名

不 REVERT
指定上下文切换不能恢复到以前的上下文。 NOREVERT选项只能在临时层面使用。

关于恢复到前述上下文的更多信息,请参见 REVERT (Transact-SQL)

饼干变 @varbinary_variable
指定只有当调用 REVERT WITH COOKIE语句包含正确的 @varbinary_variable 值时,执行上下文才能恢复到之前的上下文。 数据库引擎将 cookie 传递给 @varbinary_variable。 COOKIE INTO 选项只能在临时级别使用。

@varbinary_variablevarbinary(8000)

注意

cookie OUTPUT 参数现记载为 varbinary(8000),这是正确的最大长度 。 但是,当前执行返回 varbinary(100)。 应用程序应保留 varbinary(8000),以便当 cookie 在将来的版本中返回大小增量时,应用程序可继续正确运行。

CALLER
当在模块内部使用时,指定模块内部的语句在模块调用方的上下文中执行。 当在模块外部使用时,语句没有任何操作。

注意

此选项在Azure Synapse Analytics中不可用。

备注

执行上下文中的更改在下列操作之一发生之前一直有效:

  • 又一 EXECUTE AS 则声明被运行。

  • REVERT会进行声明。

  • 删除会话。

  • 命令已执行退出的存储过程或触发器。

你可以通过在多个主体上多次调用该 EXECUTE AS 语句来创建一个执行上下文栈。 调用时,语 REVERT 句会切换上下文到上下文栈中登录人或下一层用户。 有关此行为的示例,请参阅示例 A

指定用户名或登录名

context_specification> 中指定的EXECUTE AS<用户名或登录名必须分别作为 sys.database_principalssys.server_principals 的主体存在,否则该EXECUTE AS语句将失败。 此外,还必须为该主体授予 IMPERSONATE 权限。 除非调用方是数据库所有者,或者是 sysadmin 固定服务器角色的成员,即使用户通过Windows组成员身份访问SQL Server的数据库或实例,主体也必须存在。 例如,假设条件如下:

  • CompanyDomain\SQLUsers 组拥有 Sales 数据库的访问权限 。

  • CompanyDomain\SqlUser1 是 SQLUsers 的成员,因此具有对 Sales 数据库的隐式访问权限 。

虽然 CompanyDomain\SqlUser1 可通过 SQLUsers 组的成员身份访问数据库,但语句 失败,因为 未在数据库中作为主体存在 。

如果用户是孤儿(关联登录已不存在),且用户创建时未使用WITHINEDLOGINEXECUTE AS,则该用户将失败。

最佳做法

指定具有执行会话中操作所需的最低特权的登录名或用户。 例如,如果只需要数据库级别的权限,则不要指定具有服务器级别权限的登录名;或者除非需要这些权限,否则不要指定数据库所有者帐户。

注意

只要 数据库引擎 能够解析名称,该EXECUTE AS语句就能成功。 如果域用户存在,Windows可能无法解析数据库引擎的用户,即使Windows用户无权访问SQL Server。 这可能会导致登录时,没有访问SQL Server的登录名似乎已登录,但模拟登录名将仅具有授予公共或来宾的权限。

安全注意事项

在dbo所有权上下文下执行,例如使用语句 EXECUTE AS USER = 'dbo',会改变显式 DENY 权限的评估方式。 当你将执行上下文切换到DBO所有权上下文时,针对原始调用主体的基于权限 DENY 的限制在模拟期间不会被强制执行。 因此,能够切换执行上下文为 dbo 的主体,例如通过加入 db_owner 固定数据库角色,执行那些本应被显式 DENY 权限阻挡的操作。

此为有意行为。 授予允许所有权模拟的权限时,请考虑到这一点。 DENY 权限不能作为补偿控制来限制可作为 DBO 执行的主体的有效权限。

使用 WITH NO REVERT

当 EXECUTE AS 语句包含可选的 WITH NO REVERT 子句时,会话的执行上下文无法通过使用 REVERT 或执行其他 EXECUTE AS 语句来重置。 由该语句设置的上下文在删除会话之前一直保持有效。

当指定 WITH NO REVERT COOKIE = @varbinary_variable 子句时,SQL Server 数据库引擎 将 cookie 值传递给 @varbinary_variable。 该语句所设定的执行上下文只有在调用 REVERT WITH COOKIE = @varbinary_variable 语句包含相同的 @varbinary_variable 值时,才能恢复到之前的上下文。

该选项在使用连接池的环境中非常有用。 连接池是指维护一组数据库连接,以使应用程序服务器上的应用程序能够重用它们。 由于传递给 @varbinary_variable 的值只有调用者知道, EXECUTE AS 调用者可以保证他们建立的执行上下文不会被其他人更改。

确定原始登录

使用 ORIGINAL_LOGIN 函数返回连接到SQL Server实例的登录名。 您可以在具有众多显式或隐式上下文切换的会话中使用该函数返回原始登录的标识。

权限

登录时要指定 EXECUTE AS ,呼叫者必须对指定登录名拥有 IMPERSONATE 权限,且不得被拒绝任何 IMHONATE LOGIN 权限。 要指定 EXECUTE AS 数据库用户,调用者必须对指定用户名拥有 IMPERSONATE 权限。 当指定 CALLER 时EXECUTE AS,无需 IMPERSONATE 权限。

示例

A. 使用 EXECUTE AS 和 REVERT 切换上下文

以下示例使用多个主体创建上下文执行堆栈。 然后使用 REVERT 语句将执行上下文重置为上一个调用方。 将多次执行 REVERT 语句以向上移动堆栈,直到将执行上下文设置为原始调用方为止。

USE AdventureWorks2022;  
GO  
--Create two temporary principals  
CREATE LOGIN login1 WITH PASSWORD = 'J345#$)thb';  
CREATE LOGIN login2 WITH PASSWORD = 'Uor80$23b';  
GO  
CREATE USER user1 FOR LOGIN login1;  
CREATE USER user2 FOR LOGIN login2;  
GO  
--Give IMPERSONATE permissions on user2 to user1  
--so that user1 can successfully set the execution context to user2.  
GRANT IMPERSONATE ON USER:: user2 TO user1;  
GO  
--Display current execution context.  
SELECT SUSER_NAME(), USER_NAME();  
-- Set the execution context to login1.   
EXECUTE AS LOGIN = 'login1';  
--Verify the execution context is now login1.  
SELECT SUSER_NAME(), USER_NAME();  
--Login1 sets the execution context to login2.  
EXECUTE AS USER = 'user2';  
--Display current execution context.  
SELECT SUSER_NAME(), USER_NAME();  
-- The execution context stack now has three principals: the originating caller, login1 and login2.  
--The following REVERT statements will reset the execution context to the previous context.  
REVERT;  
--Display current execution context.  
SELECT SUSER_NAME(), USER_NAME();  
REVERT;  
--Display current execution context.  
SELECT SUSER_NAME(), USER_NAME();  
  
--Remove temporary principals.  
DROP LOGIN login1;  
DROP LOGIN login2;  
DROP USER user1;  
DROP USER user2;  
GO  

以下示例将会话的执行上下文设置为指定用户,并指定 WITH COOKIE INTO @varbinary_variable 子句。 REVERT 语句必须指定传递给 @cookie 语句中的 EXECUTE AS 变量的值,否则,无法成功将上下文恢复为该调用方。 若要执行此示例,必须存在示例 A 中所创建的 login1 登录名和 user1 用户。

DECLARE @cookie VARBINARY(8000);  
EXECUTE AS USER = 'user1' WITH COOKIE INTO @cookie;  
-- Store the cookie in a safe location in your application.  
-- Verify the context switch.  
SELECT SUSER_NAME(), USER_NAME();  
--Display the cookie value.  
SELECT @cookie;  
GO  
-- Use the cookie in the REVERT statement.  
DECLARE @cookie VARBINARY(8000);  
-- Set the cookie value to the one from the SELECT @cookie statement.  
SET @cookie = <value from the SELECT @cookie statement>;  
REVERT WITH COOKIE = @cookie;  
-- Verify the context switch reverted.  
SELECT SUSER_NAME(), USER_NAME();  
GO  

另请参阅

REVERT (Transact-SQL)
EXECUTE AS 条款(Transact-SQL)