與SQL 2005之前的版本相比,2005及之后的版本對(duì)數(shù)據(jù)庫對(duì)象的管理及查詢的執(zhí)行上下文行為做了兩個(gè)重要的改變:
1. 用戶-架構(gòu)(User-Schema)分離。即用戶不再作為數(shù)據(jù)庫對(duì)象的直接擁有者(owner),而是在數(shù)據(jù)庫對(duì)象和用戶之前加了一層schema。Schema即數(shù)據(jù)庫對(duì)象的集合,用戶可以擁有多個(gè)schema,每個(gè)用戶有一個(gè)default schema。
2. 執(zhí)行查詢的時(shí)候可以切換用戶上下文。這包括在批處理中通過EXECUTE AS語句直接切換上下文,以及另一個(gè)更常見的用法:在創(chuàng)建存儲(chǔ)過程或其它模塊時(shí)指定用戶執(zhí)行的上下文(WITH EXECUTE AS)。
關(guān)于第二點(diǎn),有一個(gè)有意思的實(shí)驗(yàn):
1. 創(chuàng)建一個(gè)測(cè)試數(shù)據(jù)庫及表:
CREATE DATABASE mydb
go
USE mydb
go
create table dbo.tbl_TestPer(ID INT, name sysname)
go
INSERT INTO tbl_TestPer SELECT 1, 'Iori'
2. 創(chuàng)建如下存儲(chǔ)過程:
CREATE PROC [dbo].[sp_TestPer1]
WITH EXECUTE AS CALLER
AS
BEGIN
SELECT SYSTEM_USER, CURRENT_USER
SELECT * FROM dbo.tbl_TestPer
END
3. 創(chuàng)建一個(gè)測(cè)試用戶并修改其權(quán)限:
CREATE LOGIN testusr WITH
go
CREATE USER testusr FROM LOGIN testusr
go
GRANT CONNECT TO testusr
go
DENY SELECT ON dbo.tbl_TestPer TO testusr
go
GRANT EXECUTE ON dbo.sp_TestPer1 TO test
go
4. 以testusr登錄并執(zhí)行如下語句,可以成功查詢到記錄
EXEC mydb..[sp_TestPer1]
這個(gè)時(shí)候的testusr用戶實(shí)際上是沒有權(quán)限查看tbl_TestPer表的,那么它是如何成功執(zhí)行SELECT語句的呢?答案就在于Ownership chaining。由于sp_TestPer1和tbl_TestPer都屬于schema dbo,而dbo這個(gè)schema的擁有者是用戶dbo(好像有點(diǎn)繞),所以第二次對(duì)SELECT 語句的權(quán)限檢查直接被by pass了。在聯(lián)機(jī)叢書中有如下描述:
Regardless of the execution context that is specified in the module, the following actions always apply:
因此要讓SQL在用戶在執(zhí)行存儲(chǔ)過程的時(shí)候?qū)σ玫膶?duì)象進(jìn)行權(quán)限檢查,需要將存儲(chǔ)過程與其引用的對(duì)象放在不同的schema下面,被不同的數(shù)據(jù)庫用戶所擁有。比如可以將表轉(zhuǎn)到guest schema下面:
ALTER SCHEMA guest TRANSFER dbo.tbl_TestPer
go
再修改存儲(chǔ)過程使其指向轉(zhuǎn)移過的表:
ALTER PROC dbo.sp_TestPer1
WITH EXECUTE AS CALLER
AS
BEGIN
SELECT SYSTEM_USER, CURRENT_USER
SELECT * FROM guest.tbl_TestPer
END
這時(shí)再用testuser執(zhí)行存儲(chǔ)過程將遇到錯(cuò)誤229。
聯(lián)系客服