在模块中使用 EXECUTE AS
EXECUTE AS 可以用于定义函数、过程、队列和触发器等用户定义模块的执行上下文。例如,可以将执行上下文从模块调用方切换到模块所有者或指定的用户。在早期版本的 SQL Server 中,始终在模块调用方上下文中执行这些模块。
通过指定执行模块的上下文,可以控制数据库引擎使用哪个用户帐户来验证是否对模块引用的任何对象拥有权限。这有助于人们更灵活、有力地管理用户定义的模块及其所引用对象所形成的对象链中的权限。模块用户只需要具有执行模块本身的权限;而不需要对被引用对象具有明确的权限。只有运行该模块的用户才必须对该模块所访问的对象具有权限。
EXECUTE AS CALLER
EXECUTE AS CALLER 指定在模块调用方的上下文中执行该模块中的语句。
在下列情况下应使用 EXECUTE AS CALLER:
您希望模块中的语句作为调用方用户来执行。
您希望针对调用用户对模块中的语句进行基本权限检查,并且只依赖所有权链接来跳过对基础对象的权限检查。请记住,所有权链接仅适用于 DML 语句。有关所有权链接的详细信息,请参阅所有权链。
应用程序不要求对用户隐藏基础被引用对象,或者您只引用所有权相同的对象因而可以依赖所有权链接来隐藏架构。
您希望维持 SQL Server 2000 行为。
EXECUTE AS CALLER 应用场景
Mary 创建了一个引用某个表的存储过程,她不拥有该表,但具有对该表的 SELECT 权限。她在 CREATE PROCEDURE 语句中指定了 EXECUTE AS CALLER,如下例中所示:
CREATE PROCEDURE AccessTable
WITH EXECUTE AS CALLER
AS SELECT * FROM dbo.SomeTable;
然后,Mary 将授予 Scott 对存储过程的 EXECUTE 权限。当 Scott 执行存储过程时,数据库引擎将验证他(调用方)是否具有执行该存储过程的权限。Scott 拥有 EXECUTE 权限,但是由于 Mary 不是被引用表的所有者,因此数据库引擎将检查 Scott 是否对该表具有权限。如果 Scott 没有权限,则该存储过程语句将失败。
EXECUTE AS user_name
EXECUTE AS user_name 将指定在 user_name 中所指定用户的上下文中执行该模块中的语句。
在下列情况下应使用 EXECUTE AS user_name:
您希望在指定用户的上下文中执行模块中的语句。
您不能依赖所有权链接(例如,模块访问具有不同所有权的对象)来隐藏基础架构,并且希望避免授予对那些被引用对象的权限。
您希望创建自定义权限集。例如,为了提供对一般不能授予特定权限的 DDL 操作的权限。有关详细信息,请参阅使用 EXECUTE AS 创建自定义权限集。
注意 无法删除被指定为模块执行上下文的用户,直到该模块的执行上下文被更改为止。
EXECUTE AS user_name 应用场景
Mary 创建了一个引用某个表的存储过程,她不拥有该表,但具有对该表的 SELECT 权限。她在 CREATE PROCEDURE 语句中指定了 EXECUTE AS 'Mary',如下例中所示:
CREATE PROCEDURE AccessMyTable
WITH EXECUTE AS 'Mary'
AS SELECT * FROM dbo.MyTable;
Mary 授予 Scott 对该存储过程的 EXECUTE 权限。当 Scott 执行存储过程时,数据库引擎将验证他是否具有执行该存储过程的权限;但是将检查 Mary 是否对被引用表具有权限。在此应用场景中,即使 Scott 并不直接对该表具有 SELECT 权限,他也可以通过该过程来访问数据,因为该过程是在 Mary 的上下文中运行的,而 Mary 具有访问该表中数据的权限。
EXECUTE AS SELF
EXECUTE AS SELF 相当于其中指定的用户为创建或修改模块的人的 EXECUTE AS user_name。
在下列情况下应使用 EXECUTE AS SELF:
您希望使用一种快捷方式来指定在您自己的上下文中运行您所创建或修改的模块的语句。
您的某个应用程序要为调用模块的用户创建模块,并且您希望使用这些用户作为执行上下文来创建这些模块。在这种情况下,您在设计时不知道调用用户的名称。
EXECUTE AS OWNER
EXECUTE AS OWNER 指定在模块当前所有者的上下文中执行该模块中的语句。如果模块没有指定的所有者,则使用模块架构的所有者。
在以下情况下应使用 EXECUTE AS OWNER:
- 您希望能够更改模块的所有者而不必修改该模块本身。也就是说,OWNER 将自动映射为模块运行时的当前所有者。
OWNER 是模块的明确所有者,如果没有明确的所有者,则 OWNER 就是执行模块时的模块架构所有者。OWNER 必须是单独帐户而不是组或角色。如果模块指定了 EXECUTE AS OWNER 并且具有明确的所有者,不能将模块的所有权更改为组或角色。如果架构包含指定了 EXECUTE AS OWNER 的模块并且模块没有明确的所有者,则不能将架构的所有权更改为角色或组。
EXECUTE AS OWNER 应用场景
Mary 创建了一个存储过程来引用她所拥有的表。她在 CREATE PROCEDURE 语句中指定了 EXECUTE AS OWNER,如下例中所示:
CREATE PROCEDURE Mary.AccessMyTable
WITH EXECUTE AS OWNER
AS SELECT * FROM Mary.MyTable;
Mary 授予 Scott 对该存储过程的 EXECUTE 权限。当 Scott 执行存储过程时,数据库引擎将验证他是否具有执行该存储过程的权限;但是将检查 Mary 是否对被引用表具有权限,因为她是该过程的当前所有者。Mary 决定离开公司,并将过程和表的所有权更改为 Tom。更改了所有权之后,当 Scott 执行该存储过程时,他仍然能够通过该过程来访问数据,因为 OWNER 已自动映射为 Tom。