EXECUTE AS (Transact-SQL)
設定工作階段的執行內容。
根據預設,工作階段會在使用者登入時啟動,而在使用者登出時結束。工作階段期間的所有作業是依對該使用者的權限檢查而定。執行 EXECUTE AS 陳述式時,工作階段的執行內容會切換到指定的登入或使用者名稱。在內容切換之後,權限檢查是對該帳戶的登入和使用者安全性 Token,而不是對呼叫 EXECUTE AS 陳述式的人員。基本上,使用者或登入帳戶的模擬是在工作階段或模組執行的期間,否則會明確還原內容切換。如需有關執行內容的詳細資訊,請參閱<了解執行內容>。如需有關內容切換的詳細資訊,請參閱<瞭解內容切換>。
語法
{ EXEC | EXECUTE } AS <context_specification>
[;]
<context_specification>::=
{ LOGIN | USER } ='name'
[ WITH { NO REVERT | COOKIE INTO @varbinary_variable } ]
| CALLER
引數
LOGIN
指定您要模擬的執行內容是登入。模擬範圍是在伺服器層級。USER
指定您要模擬的內容是目前資料庫中的使用者。模擬範圍僅限於目前資料庫。通往資料庫使用者的內容切換不會繼承該使用者的伺服器層級權限。重要事項 如果通往資料庫使用者的內容切換在使用中,任何人想要存取資料庫以外的資源,都會導致陳述式失敗。其中包括 USE database 陳述式、分散式查詢,以及參考另一個使用三或四部分識別碼之資料庫的查詢。若要擴充目前資料庫以外的內容切換範圍,請參閱<使用 EXECUTE AS 擴充資料庫模擬>。
'name'
這是有效的使用者或登入名稱。name 必須是系統管理員 (sysadmin) 固定伺服器角色的成員,或者以主體形式分別存在於 sys.database_principals 或 sys.server_principals 中。name 可以指定為本機變數。
name 必須是單一帳戶,不可以是群組、角色、憑證、金鑰或內建帳戶,例如 NT AUTHORITY\LocalService、NT AUTHORITY\NetworkService 或 NT AUTHORITY\LocalSystem。
如需詳細資訊,請參閱本主題稍後的指定使用者或登入名稱。
NO REVERT
指定內容切換不能還原回先前的內容。如需有關還原到先前內容的詳細資訊,請參閱<REVERT (Transact-SQL)>。
COOKIE INTO @varbinary_variable
指定只有當呼叫的 REVERT WITH COOKIE 陳述式包含正確的 @varbinary_variable 值時,執行內容才能還原回先前的內容。Database Engine 會將 Cookie 傳遞給 @varbinary_variable。@ varbinary_variable 為 varbinary(100)。
CALLER
用於模組內部時,指定模組內部的陳述式是在模組呼叫端的內容中執行。用於模組外部時,陳述式沒有動作。
備註
執行內容中的變更持續有效,直到發生下列項目之一為止:
執行另一個 EXECUTE AS 陳述式。
執行 REVERT 陳述式。
卸除工作階段。
您可以藉由跨多個主體多次呼叫 EXECUTE AS 陳述式來建立執行內容堆疊。REVERT 陳述式被呼叫時,會將內容切換到內容堆疊中上一層級的登入或使用者。如需這個行為的示範,請參閱範例 A。
指定使用者或登入名稱
在 EXECUTE AS <context_specification> 中指定的使用者或登入名稱必須以主體形式分別存在於 sys.database_principals 或 sys.server_principals 中,否則 EXECUTE AS 陳述式就會失敗。此外,還必須授與主體的 IMPERSONATE 權限。除非呼叫端是資料庫擁有者或是系統管理員 (sysadmin) 固定伺服器角色的成員,否則主體必須存在,即使使用者透過 Windows 群組成員資格存取 SQL Server 的資料庫或執行個體也一樣。例如,假設有下列情況:
CompanyDomain\SQLUsers 群組擁有 Sales 資料庫的存取權。
CompanyDomain\SqlUser1 是 SQLUsers 的成員,因此對 Sales 資料庫擁有隱含的存取權。
雖然 CompanyDomain\SqlUser1 有權透過 SQLUsers 群組中的成員資格來存取資料庫,但是 EXECUTE AS USER = 'CompanyDomain\SqlUser1' 陳述式會失敗,因為 CompanyDomain\SqlUser1 並未以主體形式存在於資料庫中。
如果使用者被遺棄 (相關聯的登入不存在),而且使用者並非使用 WITHOUT LOGIN 建立的,該使用者的 EXECUTE AS 將會失敗。
最佳作法
指定一個登入或使用者,它具有執行工作階段中作業所需要的最低權限。例如,如果只需要資料庫層級權限,就不要指定具有伺服器層級權限的登入名稱;或者,除非需要其權限,否則不要指定資料庫擁有者帳戶。
注意 |
---|
只要 Database Engine 可以解析名稱,EXECUTE AS 陳述式就可以成功。如果網域使用者存在,Windows 可能可以解析 Database Engine 的使用者,即使 Windows 使用者沒有 SQL Server 的存取權也一樣。這可能會導致下列狀況:沒有 SQL Server 存取權的登入似乎已登入,不過模擬的登入只有授與 public 或 guest 的權限。 |
使用 WITH NO REVERT
當 EXECUTE AS 陳述式包括選擇性的 WITH NO REVERT 子句時,不能使用 REVERT 或藉由執行另一個 EXECUTE AS 陳述式來重設工作階段的執行內容。陳述式設定的內容會持續有效,直到卸除工作階段為止。
指定 WITH NO REVERT COOKIE = @varbinary_variable 子句時,SQL Server Database Engine 會將 Cookie 值傳遞給 @varbinary_variable。只有當呼叫的 REVERT WITH COOKIE = @varbinary_variable 陳述式包含相同的 @varbinary_variable 值時,該陳述式所設定的執行內容才能還原到先前的內容。
這個選項在使用連接共用的環境中相當有用。連接共用是資料庫連接群組的維護,這些連接是供應用程式伺服器上的應用程式重複使用。因為傳送到 @varbinary_variable 的值只有 EXECUTE AS 陳述式的呼叫者知道,呼叫者可以保證其所建立的執行內容不會被別人變更。
決定原始登入
使用 ORIGINAL_LOGIN 函數來傳回連接到 SQL Server 執行個體的登入名稱。您可以利用這個函數來傳回有許多明確或隱含內容切換的工作階段中原始登入的識別。
權限
若要指定某項登入的 EXECUTE AS 權限,則這位呼叫者必須具有指定之登入名稱的 IMPERSONATE 權限。若要指定資料庫使用者的 EXECUTE AS 權限,則這位呼叫者必須具有指定之使用者名稱的 IMPERSONATE 權限。當指定 EXECUTE AS CALLER 時,不需要 IMPERSONATE 權限。
範例
A. 使用 EXECUTE AS 和 REVERT 來切換內容
下列範例會利用多個主體來建立一個內容執行堆疊。然後再用 REVERT 陳述式,將執行內容重設為前一個呼叫者。REVERT 陳述式在上移堆疊時會執行多次,直到執行內容設為原始呼叫者為止。
USE AdventureWorks2008R2;
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
B. 使用 WITH COOKIE 子句
下列範例會將工作階段的執行內容設為指定的使用者,並且指定 REVERT WITH COOKIE = @varbinary_variable 子句。REVERT 陳述式必須指定傳遞給 EXECUTE AS 陳述式中之 @cookie 變數的值,才能順利將內容還原回呼叫端。若要執行這個範例,則必須具備在範例 A 中建立的 login1 登入和 user1 使用者。
DECLARE @cookie varbinary(100);
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(100);
-- 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