EXECUTE AS 子句 (Transact-SQL)

適用於:SQL ServerAzure SQL DatabaseAzure SQL 受控執行個體

在 SQL Server 中,您可以定義下列使用者自訂模組的執行內容:函數 (內嵌資料表值函式除外)、程序、佇列和觸發程序。

您可以指定執行模組的內容,來控制資料庫引擎是使用哪一個使用者帳戶,以驗證該模組參考之物件的權限。 此舉可以在使用者自訂模組以及其所參考物件之間的物件鏈結管理權限時,提供更大的彈性和控制權。 您只需要授與模組本身的權限給使用者即可,不必授與使用者參考物件的明確權限。 只有執行模組的使用者,必須具有模組所存取之物件的權限。

Transact-SQL 語法慣例

Syntax

本節描述 的 EXECUTE AS SQL Server 語法。

函式(內嵌資料表值函式除外)、預存程式和 DML 觸發程式:

{ EXEC | EXECUTE } AS { CALLER | SELF | OWNER | 'user_name' }

具有資料庫範圍的 DDL 觸發程式:

{ EXEC | EXECUTE } AS { CALLER | SELF | 'user_name' }

具有伺服器範圍和登入觸發程式的 DDL 觸發程式:

{ EXEC | EXECUTE } AS { CALLER | SELF | 'login_name' }

佇列:

{ EXEC | EXECUTE } AS { SELF | OWNER | 'user_name' }

注意

若要檢視 SQL Server 2014 (12.x) 和舊版的 Transact-SQL 語法,請參閱 舊版檔

引數

CALLER

指定模組內的陳述式,是在該模組的呼叫者內容當中執行。 執行該模組的使用者,不僅必須具有模組本身的適當權限,也必須具有該模組所參考之任何資料庫物件的權限。

CALLER 是佇列以外的所有模組的預設值,與 SQL Server 2005 (9.x) 行為相同。

CALLER無法在 或 ALTER QUEUE 語句中 CREATE QUEUE 指定。

SELF

EXECUTE AS SELF 相當於 EXECUTE AS <user_name> ,其中指定的使用者是建立或改變模組的人員。 建立或修改模組的人員的實際使用者識別碼會儲存在 或 sys.service_queues 目錄檢視的資料 execute_as_principal_idsys.sql_modules 行中。

SELF 是佇列的預設值。

注意

若要變更目錄檢視中 sys.service_queues 資料行的使用者識別碼 execute_as_principal_id ,您必須在 語句中 ALTER QUEUE 明確指定 EXECUTE AS 設定。

OWNER

指定模組內的語句會在模組目前擁有者的內容中執行。 如果模組沒有指定的擁有者,則會使用模組架構的擁有者。 OWNER 無法針對 DDL 或登入觸發程式指定。

重要

OWNER 必須對應至單一帳戶,而且不能是角色或群組。

'user_name'

指定模組內的陳述式,在 user_name 指定的使用者內容中執行。 會針對 user_name 來驗證模組內任何物件的權限。 無法針對具有伺服器範圍或登入觸發程式的 DDL 觸發程式指定user_name。 請改為使用 login_name

user_name 必須存在於目前資料庫中,而且必須是單一帳戶。 user_name不能是群組、角色、憑證、金鑰或內建帳戶,例如 NT AUTHORITY\LocalServiceNT AUTHORITY\NetworkServiceNT AUTHORITY\LocalSystem

執行內容的使用者識別碼會儲存在中繼資料中,而且可以在 或 sys.assembly_modules 目錄檢視的資料 execute_as_principal_idsys.sql_modules 行中檢視。

' login_name '

指定模組內的陳述式,在 login_name 所指定的 SQL Server 登入內容中執行。 會針對 login_name 來驗證模組內任何物件的權限。 login_name 只能針對具有伺服器範圍的 DDL 觸發程序或登入觸發程序來指定。

login_name 不能是群組、角色、憑證、金鑰或內建帳戶,例如 NT AUTHORITY\LocalServiceNT AUTHORITY\NetworkServiceNT AUTHORITY\LocalSystem

備註

資料庫引擎如何評估模組內參考物件的權限,會隨著呼叫物件和所參考物件之間的擁有權鏈結而不同。 在舊版的 SQL Server 中,擁有權鏈結是唯一可以避免授與參考物件存取權給呼叫使用者的方法。

擁有權鏈結具有下列限制:

  • 僅適用于 DML 語句: SELECTINSERTUPDATEDELETE
  • 呼叫和被呼叫物件的擁有者必須相同。
  • 不適用於模組內的動態查詢。

無論模組指定的執行內容為何,下列動作一定適用:

  • 執行模組時,資料庫引擎會先確認執行模組的使用者具有 EXECUTE 模組的許可權。

  • 擁有權鏈結規則仍然適用。 換句話說,如果呼叫和被呼叫物件的擁有者一樣,就不會檢查基礎物件的任何權限。

當使用者執行已指定在 以外的 CALLER 內容中執行的模組時,會檢查使用者執行模組的許可權,但模組所存取之物件的其他許可權檢查會針對 子句中指定的 EXECUTE AS 使用者帳戶執行。 執行該模組的使用者,實際上就是模擬指定的使用者。

模組子 EXECUTE AS 句中指定的內容只有在模組執行期間才有效。 模組執行完畢之後,內容便還原給呼叫者。

指定使用者或登入名稱

在修改模組以在另一個內容下執行之前,無法卸載模組子句中指定的 EXECUTE AS 資料庫使用者或伺服器登入。

子句中指定的 EXECUTE AS 使用者或登入名稱必須分別以 或 sys.server_principals 中的 sys.database_principals 主體存在,否則建立或改變模組作業會失敗。 另外,建立或變更模組的使用者,必須具有該主體的 IMPERSONATE 權限。

如果使用者透過 Windows 群組成員資格隱含存取 SQL Server 的資料庫或實例,當模組存在下列其中一項需求時,就會隱含地建立 子句中指定的 EXECUTE AS 使用者:

  • 指定的使用者或登入,是 sysadmin 固定伺服器角色的成員。
  • 建立該模組的使用者,有權建立主體。

如果這兩項需求都不符合,則建立模組作業便會失敗。

重要

如果 SQL Server (MSSQLSERVER) 服務是以本機帳戶執行(本機服務或本機使用者帳戶),則它不會有許可權取得 子句中所 EXECUTE AS 指定之 Windows 網域帳戶的群組成員資格。 此舉會使模組執行作業失敗。

例如,假設有下列情況:

  • CompanyDomain\SQLUsers group 可以存取 Sales 資料庫。

  • CompanyDomain\SqlUser1 是 的成員 SQLUsers ,因此可以存取 Sales 資料庫。

  • 建立或變更該模組的使用者,有權建立主體。

在執行下列 CREATE PROCEDURE 陳述式時,CompanyDomain\SqlUser1 會隱含建立為 Sales 資料庫中的資料庫主體。

USE Sales;
GO
CREATE PROCEDURE dbo.usp_Demo
WITH EXECUTE AS 'CompanyDomain\SqlUser1'
AS
SELECT USER_NAME();
GO

使用 EXECUTE AS CALLER 獨立語句

EXECUTE AS CALLER使用模組內的獨立語句,將執行內容設定為模組的呼叫端。

假設下列預存程序是由 SqlUser2 呼叫。

CREATE PROCEDURE dbo.usp_Demo
WITH EXECUTE AS 'SqlUser1'
AS
SELECT USER_NAME(); -- Shows execution context is set to SqlUser1.
EXECUTE AS CALLER;
SELECT USER_NAME(); -- Shows execution context is set to SqlUser2, the caller of the module.
REVERT;
SELECT USER_NAME(); -- Shows execution context is set to SqlUser1.
GO

使用 EXECUTE AS 定義自訂許可權集合

當您想要定義自訂許可權集合時,指定模組的執行內容會很有用。 例如,某些動作,例如 TRUNCATE TABLE 沒有可授與的許可權。 藉由將 TRUNCATE TABLE 語句併入模組內,並指定該模組以具有改變數據表許可權的使用者身分執行,您可以將許可權擴充為將資料表截斷至您在模組上授 EXECUTE 與許可權的使用者。

若要以指定的執行內容來檢視模組定義,請使用 sys.sql_modules (Transact-SQL) 目錄檢視。

最佳做法

指定一個登入或使用者,它具有執行在模組中定義的作業時所需要的最低權限。 例如,除非需要這些許可權,否則請勿指定資料庫擁有者帳戶。

權限

若要執行以 EXECUTE AS 指定的模組,呼叫端必須具有 EXECUTE 模組的許可權。

若要執行以 EXECUTE AS 指定的 CLR 模組,以存取另一個資料庫或伺服器中的資源,目標資料庫或伺服器必須信任模組的來源資料庫驗證器(源資料庫)。

若要在建立或修改模組時指定 EXECUTE AS 子句,您必須擁有 IMPERSONATE 指定主體的許可權,以及建立模組的許可權。 您永遠都可以模擬自己本身。 如果未指定或 EXECUTE AS CALLER 指定任何執行內容, IMPERSONATE 則不需要許可權。

若要指定 可透過 Windows 群組成員資格隱含存取資料庫的login_name user_name ,您必須具有 CONTROL 資料庫的許可權。

範例

下列範例會在 AdventureWorks2022 資料庫中建立預存程式,並將執行內容指派給 OWNER

CREATE PROCEDURE HumanResources.uspEmployeesInDepartment @DeptValue INT
    WITH EXECUTE AS OWNER
AS
SET NOCOUNT ON;

SELECT e.BusinessEntityID,
    c.LastName,
    c.FirstName,
    e.JobTitle
FROM Person.Person AS c
INNER JOIN HumanResources.Employee AS e
    ON c.BusinessEntityID = e.BusinessEntityID
INNER JOIN HumanResources.EmployeeDepartmentHistory AS edh
    ON e.BusinessEntityID = edh.BusinessEntityID
WHERE edh.DepartmentID = @DeptValue
ORDER BY c.LastName,
    c.FirstName;
GO

-- Execute the stored procedure by specifying department 5.
EXECUTE HumanResources.uspEmployeesInDepartment 5;
GO