瞭解內容切換
執行內容是由連接到工作階段,或執行 (呼叫) 模組的使用者或登入所決定。它會根據檢查哪些權限可執行陳述式或執行動作的結果來建立身分。在 SQL Server 中,執行 EXECUTE AS 陳述式或在模組中指定 EXECUTE AS 子句可將執行內容切換到另一位使用者或登入。內容切換之後,SQL Server 會檢查該帳戶的登入和使用者的權限,而不是呼叫 EXECUTE AS 陳述式或模組人員的權限。資料庫使用者或 SQL Server 登入是在工作階段或模組執行期間的其餘時間進行模擬,或直到明確還原內容切換為止。如需有關執行內容的詳細資訊,請參閱<瞭解執行內容>。
明確內容切換
在 EXECUTE AS 陳述式中指定使用者或登入名稱可以明確變更工作階段或模組的執行內容。在發生下列其中一個事件之前,模擬會持續有效:
工作階段已卸除。
內容被切換成其他登入或使用者。
內容被還原成先前的執行內容。
使用 EXECUTE AS 明確模擬另一個使用者與 SQL Server 舊版的 SETUSER 類似。如需詳細資訊,請參閱<EXECUTE AS 與 SETUSER>。
明確伺服器層級內容切換
若要在伺服器層級切換執行內容,請使用 EXECUTE AS LOGIN = 'login_name' 陳述式。登入名稱必須在 sys.server_principals 中顯示成主體,而陳述式呼叫者必須具有指定登入名稱的 IMPERSONATE 權限。
當執行內容是在伺服器層級時,模擬的範圍如下所示:
login_name 的登入 Token 是由 SQL Server 的執行個體驗證,並且在該執行個體中皆有效。
login_name 的伺服器層級權限和角色成員資格則會被接受。
使用 REVERT 陳述式即可返回先前的內容。REVERT 陳述式的呼叫者,必須位在發生模擬的相同資料庫中。
範例
在下列範例中,Peter Connelly 是 Adventure Works Cycles 的網路管理員,想要為新員工 Jinghao Liuhas 建立一個 SQL Server 登入帳戶。Peter 的 SQL Server 登入沒有建立 SQL Server 登入所需的伺服器層級權限,不過他具有 adventure-works\dan1 (具有所需伺服器層級權限的 SQL Server 登入) 的 IMPERSONATE 權限。當 Peter 連接至 SQL Server 時,此工作階段的執行內容就會從 SQL Server 登入衍生。為了建立 SQL Server 登入,Peter 暫時採用 adventure-works\dan1 的執行內容。然後,他便建立登入。最後,他會讓出採用的權限。
-- Switch execution context to the adventure-works\dan1 login account.
EXECUTE AS LOGIN = 'adventure-works\dan1';
-- Create the new login account.
CREATE LOGIN Jinghao1 WITH PASSWORD = '3KHJ6dhx(0xVYsdf';
-- Revert to the previous execution context.
REVERT;
明確資料庫層級內容切換
若要在資料庫層級切換內容,請使用 EXECUTE AS USER = 'user_name' 陳述式。使用者名稱必須是 sys.database_principals 中的主體,而陳述式呼叫者必須在指定的使用者名稱有 IMPERSONATE 權限。
當執行內容是在資料庫層級時,模擬的範圍如下所示:
user_name 的使用者 Token 是由 SQL Server 的執行個體驗證,而且在目前的資料庫中有效。如需有關如何擴充目前資料庫範圍之使用者模擬的資訊,請參閱<使用 EXECUTE AS 擴充資料庫模擬>。
user_name 的資料庫層級權限和角色成員資格會被接受。明確授與給使用者 Token 之身分的伺服器層級權限,或透過角色成員資格所授與的伺服器層級權限則不會被接受。
使用 REVERT 陳述式即可返回先前的內容。REVERT 陳述式的呼叫者,必須位在發生模擬的相同資料庫中。
範例
在下列範例中,François Ajenstat 是 Adventure Works Cycles 的資料庫管理員,他想要對 AdventureWorksDW 資料庫執行 DBCC CHECKDB 陳述式,但是他沒有執行此工作的資料庫層級權限。不過他在使用者 dan1 帳戶 (有必要的權限) 上具有 IMPERSONATE 權限。
當 François 連接到 AdventureWorksDW 資料庫時,執行內容會對應到他的使用者安全性 Token。此時會對他的使用者 Token 中主要和次要主體檢查執行陳述式的權限。因為他沒有執行 DBCC CHECKDB 陳述式所需的權限,因此他要執行下列陳述式。
-- EXECUTE AS USER = 'dan1';
-- Create a table in dan1's default schema
CREATE TABLE t_NewTable( data nvarchar(100) );
go
-- Revert to the previous execution context.
REVERT
go;
隱含內容切換
在模組定義中的 EXECUTE AS 子句中指定使用者或登入名稱,可變更模組的執行內容,如預存程序、觸發程序、佇列或使用者自訂函數。
指定模組要在其中執行的內容,可以控制 SQL Server 要用哪一個使用者帳戶來驗證該模組參考物件的權限。此舉可以在使用者自訂模組以及其所參考物件之間的物件鏈結管理權限時,提供更大的彈性和控制權。您只需要授與模組本身的權限給使用者即可,不必授與參考物件的明確權限。只有模擬模組的使用者需要對模組存取的物件具有權限。
模擬的層級是由定義模擬的模組類型所決定。
伺服器層級模擬可在下列項目中定義:
- DDL 觸發程序
伺服器層級模擬的範圍與之前在「明確伺服器層級內容切換」中所定義的範圍相同。
資料庫層級模擬可在下列項目中定義:
DML 觸發程序
佇列
預存程序
使用者自訂函數
資料庫層級模擬的範圍與之前在「明確資料庫層級內容切換」中所定義的範圍相同。
如需有關隱含內容切換的詳細資訊,請參閱<在模組中使用 EXECUTE AS>。
範例
在下列範例中,Mary 是資料表 MyTable 的擁有者。她想要讓使用者 Scott 可以截斷資料表,但是 Scott 對該資料表沒有直接的權限。因此,她建立預存程序 dbo.usp_TruncateMyTable,並且授與該程序的 EXECUTE 權限給 Scott。當 Scott 執行預存程序時,Database Engine 會確認截斷資料表的權限,就像 Mary 自己在執行預存程序一樣。因為她是資料表擁有者,所以即使 Scott 對該資料表本身沒有直接的權限,陳述式還是會成功。
CREATE PROCEDURE dbo.usp_TruncateMyTable
WITH EXECUTE AS SELF
AS TRUNCATE TABLE MyDB..MyTable;