從數(shù)據(jù)行入手保護SQL Server數(shù)據(jù)安全
在當(dāng)今企業(yè)環(huán)境中,保證數(shù)據(jù)安全不是可有可無的工作。頻繁曝光的入侵和欺騙事件、薩班斯◆奧克斯利法案、HIPAA法案規(guī)定和愛國者法案等都要求我們能夠做到,將正確數(shù)據(jù)提供給正確的用戶,防止其它無權(quán)限的人訪問。一般來說,“行級安全(row-level security)”的要求是:對數(shù)據(jù)庫中的數(shù)據(jù)以行為單位,設(shè)定只有特定用戶才可以訪問。可惜的是,SQL Server數(shù)據(jù)庫并不提供內(nèi)置的行級別安全機制。
在本篇文章中,通過一個示例代碼(代碼清單1),來告訴大家一個在SQL Server中實現(xiàn)行級別安全的方法,以行為單位限定用戶的訪問權(quán)限,同時無需修改業(yè)務(wù)表的內(nèi)容,不影響應(yīng)用程序或表現(xiàn)層開發(fā)者,而且與用戶訪問數(shù)據(jù)的方式無關(guān)。該示例應(yīng)用的模擬需求為:如何增加安全性到現(xiàn)有訂單數(shù)據(jù)庫中,限制經(jīng)理只能訪問他們管理的部門或其子部門的數(shù)據(jù),而不管用戶如何獲得該表,以及針對這個數(shù)據(jù)庫開發(fā)什么樣的報表和查詢。
代碼清單1:提供了創(chuàng)建和加載示例表的腳本
--create table script
CREATE TABLE dbo.UserAccess
(
UserID varchar(20) NOT NULL,
Department varchar(50) NOT NULL
)
CREATE TABLE [dbo].[Orders](
[OrderID] [int] NOT NULL,
[CustomerName] [varchar](20) NOT NULL,
[OrderTotal] [money] NOT NULL,
[Department] [varchar](50) NOT NULL
)
CREATE TABLE dbo.Departments
(
Department varchar(50) NOT NULL,
ParentDepartment varchar(50)
)
--end create table script--script to clear then populate example tables
--clear tables
Delete from departments
Delete from orders
Delete from useraccess--insert departments table
INSERTINTO [dbo].[Departments] ([Department],[ParentDepartment]) VALUES ('North America','')
INSERT INTO [dbo].[Departments] ([Department],[ParentDepartment]) VALUES ('East','North America')
INSERT INTO [dbo].[Departments] ([Department],[ParentDepartment]) VALUES ('Southeast','East')
INSERT INTO [dbo].[Departments] ([Department],[ParentDepartment]) VALUES ('Northeast','East')
INSERT INTO [dbo].[Departments] ([Department],[ParentDepartment]) VALUES ('West','North America')
INSERT INTO [dbo].[Departments] ([Department],[ParentDepartment]) VALUES ('Southwest','West')
INSERT INTO [dbo].[Departments] ([Department],[ParentDepartment]) VALUES ('Northwest','West')--insert orders table
INSERT INTO [dbo].[Orders] ([OrderID],[CustomerName],[OrderTotal],[Department]) VALUES (1,'Harris','11.00','East')
INSERT INTO [dbo].[Orders] ([OrderID],[CustomerName],[OrderTotal],[Department]) VALUES (2,'Corrigan','22.00','Southeast')
INSERT INTO [dbo].[Orders] ([OrderID],[CustomerName],[OrderTotal],[Department]) VALUES (2,'Corrigan','22.00','Southeast')
INSERT INTO [dbo].[Orders] ([OrderID],[CustomerName],[OrderTotal],[Department]) VALUES (3,'Baldwin','33.00','Southeast')
INSERT INTO [dbo].[Orders] ([OrderID],[CustomerName],[OrderTotal],[Department]) VALUES (4,'Pillow','44.00','Northeast')
INSERT INTO [dbo].[Orders] ([OrderID],[CustomerName],[OrderTotal],[Department]) VALUES (5,'Carpenter','55.00','Northeast')
INSERT INTO [dbo].[Orders] ([OrderID],[CustomerName],[OrderTotal],[Department]) VALUES (6,'Meyer','66.00','West')
INSERT INTO [dbo].[Orders] ([OrderID],[CustomerName],[OrderTotal],[Department]) VALUES (7,'Gonzalez','77.00','Southwest')
INSERT INTO [dbo].[Orders] ([OrderID],[CustomerName],[OrderTotal],[Department]) VALUES (8,'Hall','88.00','Northwest')
INSERT INTO [dbo].[Orders] ([OrderID],[CustomerName],[OrderTotal],[Department]) VALUES (9,'Patrick','99.00','Southwest')--insert user access table
INSERT INTO [dbo].[UserAccess] ([UserID],[Department]) VALUES ('BLambert','Southwest')
INSERT INTO [dbo].[UserAccess] ([UserID],[Department]) VALUES ('MDavis','East')
INSERT INTO [dbo].[UserAccess] ([UserID],[Department]) VALUES ('MDavis','Southeast')
INSERT INTO [dbo].[UserAccess] ([UserID],[Department]) VALUES ('MDavis','Northeast')
INSERT INTO [dbo].[UserAccess] ([UserID],[Department]) VALUES ('WSimmons','Northeast')--end script to clear then populate example tables
行級別安全代碼范例
首先我們作出如下假設(shè):
◆使用SQL Server數(shù)據(jù)庫(微軟SQL Server 2000、2005或2008)
◆所有表中都有一個共同的字段,使用它來決定誰可以看什么數(shù)據(jù)(本例中就是department字段)
◆通過不同的用戶id來加強應(yīng)用程序調(diào)用數(shù)據(jù)庫的安全性,而不是通過一個單一的admin用戶id。
舉例來說,圖1所示數(shù)據(jù)結(jié)構(gòu)包含:Orders表,包含一個客戶名稱、訂單收入和銷售部門;一個部門查閱表(Departments),包含父部門字段;一個用戶訪問表(UserAccess),在用戶和他有權(quán)限查看的部門之間建立聯(lián)系。用戶訪問表的每一行數(shù)據(jù)代表一個正確的用戶/部門組合。如果一個用戶有權(quán)限訪問的部門下設(shè)許多子部門,那么這個父部門和每一個子部門在表中各占據(jù)一行數(shù)據(jù)。
圖1 該數(shù)據(jù)庫模型圖顯示了本例中所用到的表
讓訂單數(shù)據(jù)保持安全的關(guān)鍵是,通過SQL Server的表值型函數(shù)來保護它,該函數(shù)要求使用當(dāng)前用戶的id作為參數(shù)。表值型函數(shù)與其它函數(shù)一樣可以接受參數(shù),但是返回結(jié)果為一個表,而并非一個變量。在這個函數(shù)內(nèi),通過其安全屬性聯(lián)合要保護的表與用戶訪問表,將表的結(jié)果限定在與指定用戶id相關(guān)的范圍之內(nèi)。
示例1定義了一個表值型函數(shù),根據(jù)UserAccess表中的限制用戶可以查看的內(nèi)容,返回訂單數(shù)量和訂單的總收入。
示例1:創(chuàng)建保護訂單數(shù)據(jù)的表值型函數(shù)的SQL語句
CREATE FUNCTION [dbo].[GetOrderSummary] |
而圖2顯示了該函數(shù)的執(zhí)行示例,以及相關(guān)表的數(shù)據(jù)內(nèi)容,如表1、表2和表3.
圖2 表值型函數(shù)執(zhí)行示例
表1 UserAccess示例表內(nèi)容
表2 Orders示例表內(nèi)容
表3 Department表內(nèi)容
顯示受保護表內(nèi)容
通過表值型函數(shù)保護了某個表之后,你然后可以通過類似示例2的視圖將其展示給用戶。該視圖調(diào)用了上面定義的表值型函數(shù),并使用參數(shù)“user”,在SQL Server中這是一個內(nèi)置函數(shù),返回當(dāng)前活躍用戶的ID。
示例2:創(chuàng)建一個視圖讓安全用戶訪問受保護表的SQL
CREATE VIEW[dbo].[OrderSummary] |
這個視圖是用戶被授予訪問權(quán)限的唯一對象,即使用戶不具有權(quán)限使用前面的表值型函數(shù)或訪問受保護表,他也可以獲得被許可查看的數(shù)據(jù)。
實際應(yīng)用思考
在應(yīng)用程序開發(fā)實際情況中,這種方式往往需要一個以上的屬性來定義用戶行級別權(quán)限,而且往往需要對多個表應(yīng)用安全機制。
另外,不同的數(shù)據(jù)可能具有不同的安全考慮。舉例來說,一個用戶可能有權(quán)限訪問某個區(qū)域的銷售結(jié)果,但不能訪問匯總薪酬數(shù)據(jù)。在復(fù)雜的實際環(huán)境中成功運用這個戰(zhàn)略的關(guān)鍵是,收集并確認來自業(yè)務(wù)的需求,然后根據(jù)這些需求來選擇合適的屬性來實施行級別安全。
使用活動目錄的企業(yè),可以按照活動目錄組來使用這種方式獲得安全性,而并一定僅限于使用用戶ID,實現(xiàn)方法非常簡單,只需要在UserAccess表中使用活動目錄組替代用戶ID即可。
相關(guān)閱讀
薩班斯-奧克斯利法案(Sarbanes-Oxley Act)是美國立法機構(gòu)根據(jù)安然有限公司、世界通訊公司等財務(wù)欺詐事件破產(chǎn)暴露出來的公司和證券監(jiān)管問題所立的監(jiān)管法規(guī),簡稱《SOX法案》或《索克思法案》。
法案全稱《2002年公眾公司會計改革和投資者保護法案》由參議院銀行委員會主席薩班斯(Paul Sarbanes)和眾議院金融服務(wù)委員會(Committee on Financial Services)主席奧克斯利(Mike Oxley)聯(lián)合提出,又被稱作《2002年薩班斯-奧克斯利法案》。該法案對美國《1933年證券法》、《1934年證券交易法》做出大幅修訂,在公司治理、會計職業(yè)監(jiān)管、證券市場監(jiān)管等方面作出了許多新的規(guī)定。
【編輯推薦】