ADD SIGNATURE (Transact-SQL)
將數位簽章加入至預存程序、函數、組件或觸發程序。也將副署簽章加入至預存程序、函數、組件或觸發程序。
語法
ADD [ COUNTER ] SIGNATURE TO module_class::module_name
BY <crypto_list> [ ,...n ]
<crypto_list> ::=
CERTIFICATE cert_name
| CERTIFICATE cert_name [ WITH PASSWORD ='password' ]
| CERTIFICATE cert_name WITH SIGNATURE =signed_blob
| ASYMMETRIC KEY Asym_Key_Name
| ASYMMETRIC KEY Asym_Key_Name [ WITH PASSWORD ='password' ]
| ASYMMETRIC KEY Asym_Key_Name WITH SIGNATURE = signed_blob
引數
module_class
這是要加入簽章的模組類別。結構描述範圍模組的預設值是 OBJECT。module_name
這是要簽署或反簽署的預存程序、函數、組件或觸發程序的名稱。CERTIFICATE cert_name
這是用來簽署或反簽署預存程序、函數、組件或觸發程序的憑證名稱。WITH PASSWORD ='password'
這是要將憑證私密金鑰或非對稱金鑰解密所需的密碼。唯有當私密金鑰不受資料庫主要金鑰保護時,才需要這個子句。SIGNATURE = signed_blob
指定模組已簽署的二進位大型物件 (BLOB)。如果您想要傳送模組但不傳送私密金鑰,則這個子句很有用。當您使用這個子句時,只需要模組、簽章和公開金鑰,即可將簽署的二進位大型物件加入資料庫中。signed_blob 是十六進位格式的 Blob 本身。ASYMMETRIC KEY Asym_Key_Name
這是預存程序、函數、組件或觸發程序用來簽署或副署的非對稱金鑰名稱。
備註
簽署或副署的模組及用來簽署的憑證或非對稱金鑰必須已存在。模組中的每個字元都會包含在簽章計算中。這包括開頭的歸位字元和換行字元。
可用任何數目的憑證和非對稱金鑰來簽署和副署模組。
當模組變更時,會卸除模組的簽章。
如果模組包含 EXECUTE AS 子句,則主體的安全性識別碼 (SID) 也會併入成為簽署程序的一部分。
警告 |
---|
模組簽署只能用來授與權限,絕對不能用來拒絕或撤銷權限。 |
可以在 sys.crypt_properties 目錄檢視中看到有關簽章的資訊。
副署簽章
當執行簽署的模組時,簽章會暫時加入至 SQL Token,但是如果此模組執行另一個模組或是此模組結束執行,簽章將會遺失。副署簽章是一種特殊形式的簽章。副署簽章本身並不會授與任何權限,但是它可允許在呼叫副署物件的期間,保留相同憑證或非對稱金鑰所做的簽章。
例如,假設使用者 Alice 呼叫 ProcSelectT1ForAlice 程序,此程序呼叫 procSelectT1 程序,後者是從資料表 T1T1 選取而來。Alice 擁有 ProcSelectT1ForAlice 和 procSelectT1 的 EXECUTE 權限,但是沒有 T1 的 SELECT 權限,所以這整個鏈結中並未牽涉到任何擁有權鏈結。Alice 無法存取資料表 T1,不論是直接存取還是透過 ProcSelectT1ForAlice 和 procSelectT1 的使用。因為我們希望 Alice 永遠都使用 ProcSelectT1ForAlice 進行存取,所以我們不想要授與他執行 procSelectT1 的權限。我們該怎麼完成呢?
如果我們簽署 procSelectT1,好讓 procSelectT1 可以存取 T1,則 Alice 就可以直接叫用 procSelectT1,而且他不必呼叫 ProcSelectT1ForAlice。
我們可以拒絕將 procSelectT1 的 EXECUTE 權限授與給 Alice,但是 Alice 也就無法透過 ProcSelectT1ForAlice 來呼叫 procSelectT1。
只簽署 ProcSelectT1ForAlice 是不可行的,因為在呼叫 procSelectT1 時將會遺失簽章。
但是,透過用來簽署 ProcSelectT1ForAlice 的相同憑證副署 procSelectT1 時,SQL Server 會在整個呼叫鏈結中保留簽章,而且允許存取 T1。如果 Alice 嘗試直接呼叫 procSelectT1,他就無法存取 T1,因為副署簽章不會授與任何權限。例如,底下的 C 顯示這個範例的 Transact-SQL。
權限
需要物件的 ALTER 權限,以及憑證或非對稱金鑰的 CONTROL 權限。如果相關聯的私密金鑰受到密碼保護,則使用者也必須有密碼。
範例
A. 使用憑證簽署預存程序
下列範例以 HumanResourcesDP 憑證簽署預存程序 HumanResources.uspUpdateEmployeeLogin。
USE AdventureWorks;
ADD SIGNATURE TO HumanResources.uspUpdateEmployeeLogin
BY CERTIFICATE HumanResourcesDP;
GO
B. 使用已簽署的 BLOB 簽署預存程序
下列範例會建立新資料庫,並建立憑證供本範例使用。範例中還會建立一個簡單的預存程序,同時從 sys.crypt_properties 擷取簽章 BLOB。接著該程序將卸除後再重建。最後,本範例使用 WITH SIGNATURE 語法簽署該程序。
CREATE DATABASE TestSignature ;
GO
USE TestSignature ;
GO
-- Create a CERTIFICATE to sign the procedure.
CREATE CERTIFICATE cert_signature_demo
ENCRYPTION BY PASSWORD = 'pGFD4bb925DGvbd2439587y'
WITH SUBJECT = 'ADD SIGNATURE demo';
GO
-- Create a simple procedure.
CREATE PROC [sp_signature_demo]
AS
PRINT 'This is the content of the procedure.' ;
GO
-- Sign the procedure.
ADD SIGNATURE TO [sp_signature_demo]
BY CERTIFICATE [cert_signature_demo]
WITH PASSWORD = 'pGFD4bb925DGvbd2439587y' ;
GO
-- Get the signature binary BLOB for the sp_signature_demo procedure.
SELECT cp.crypt_property
FROM sys.crypt_properties AS cp
JOIN sys.certificates AS cer
ON cp.thumbprint = cer.thumbprint
WHERE cer.name = 'cert_signature_demo' ;
GO
每建立一次程序,此陳述式傳回的 crypt_property 簽章都不盡相同。請記下結果供本範例後續階段使用。本範例示範的結果為:0x831F5530C86CC8ED606E5BC2720DA835351E46219A6D5DE9CE546297B88AEF3B6A7051891AF3EE7A68EAB37CD8380988B4C3F7469C8EABDD9579A2A5C507A4482905C2F24024FFB2F9BD7A953DD5E98470C4AA90CE83237739BB5FAE7BAC796E7710BDE291B03C43582F6F2D3B381F2102EEF8407731E01A51E24D808D54B373。
-- Drop the procedure so that a new version can be created.
DROP PROC [sp_signature_demo] ;
GO
-- Re-create the procedure by using the exact text including spaces.
CREATE PROC [sp_signature_demo]
AS
PRINT 'This is the content of the procedure.' ;
GO
-- Add the signature. Use the signature BLOB obtained earlier.
ADD SIGNATURE TO [sp_signature_demo]
BY CERTIFICATE [cert_signature_demo]
WITH SIGNATURE = 0x831F5530C86CC8ED606E5BC2720DA835351E46219A6D5DE9CE546297B88AEF3B6A7051891AF3EE7A68EAB37CD8380988B4C3F7469C8EABDD9579A2A5C507A4482905C2F24024FFB2F9BD7A953DD5E98470C4AA90CE83237739BB5FAE7BAC796E7710BDE291B03C43582F6F2D3B381F2102EEF8407731E01A51E24D808D54B373 ;
GO
C. 使用副署簽章存取程序
下列範例示範副署簽章如何控制物件的存取。
-- Create tesT1 database
CREATE DATABASE testDB;
GO
USE testDB;
GO
-- Create table T1
CREATE TABLE T1 (c varchar(11));
INSERT INTO T1 VALUES ('This is T1.');
-- Create a TestUser user to own table T1
CREATE USER TestUser WITHOUT LOGIN;
ALTER AUTHORIZATION ON T1 TO TestUser;
-- Create a certificate for signing
CREATE CERTIFICATE csSelectT
ENCRYPTION BY PASSWORD = 'SimplePwd01'
WITH SUBJECT = 'Certificate used to grant SELECT on T1';
CREATE USER ucsSelectT1 FROM CERTIFICATE csSelectT;
GRANT SELECT ON T1 TO ucsSelectT1;
-- Create a principal with low privileges
CREATE LOGIN Alice WITH PASSWORD = 'SimplePwd01';
CREATE USER Alice;
-- Verify Alice cannoT1 access T1;
EXECUTE AS LOGIN = 'Alice';
SELECT * FROM T1;
REVERT;
-- Create a procedure that directly accesses T1
CREATE PROCEDURE procSelectT1 AS
BEGIN
PRINT 'Now selecting from T1...';
SELECT * FROM T1;
END;
GO
GRANT EXECUTE ON procSelectT1 to public;
-- Create special procedure for accessing T1
CREATE PROCEDURE procSelectT1ForAlice AS
BEGIN
IF USER_ID() <> USER_ID('Alice')
BEGIN
PRINT 'Only Alice can use this.';
RETURN
END
EXEC procSelectT1;
END;
GO;
GRANT EXECUTE ON procSelectT1ForAlice TO PUBLIC;
-- Verify procedure works for a sysadmin user
EXEC procSelectT1ForAlice;
-- Alice still can't use the procedure yet
EXECUTE AS LOGIN = 'Alice';
EXEC procSelectT1ForAlice;
REVERT;
-- Sign procedure to grant it SELECT permission
ADD SIGNATURE TO procSelectT1ForAlice BY CERTIFICATE csSelectT
WITH PASSWORD = 'SimplePwd01';
-- Counter sign proc_select_t, to make this work
ADD COUNTER SIGNATURE TO procSelectT1 BY CERTIFICATE csSelectT
WITH PASSWORD = 'SimplePwd01';
-- Now the proc works.
-- Note that calling procSelectT1 directly still doesn't work
EXECUTE AS LOGIN = 'Alice';
EXEC procSelectT1ForAlice;
EXEC procSelectT1;
REVERT;
-- Cleanup
USE master;
GO
DROP DATABASE testDB;
DROP LOGIN Alice;