SQL Server 2016:行級安全

jopen 9年前發布 | 9K 次閱讀 SQL Server

 

對于SQL Server,一個常見的批評是,其安全模型只能識別表和列。用戶如果希望以行為單位應用安全規則,就需要使用存儲過程或表值函數來模擬,然后找一種方法,確保它們不會被繞開。在SQL Server 2016中,那不再是個問題。

實現

SQL Server 2016(及SQL Azure)中的 行級安全 基于一個專門設計的內聯表值函數。該函數要么返回一個只包含值1的行,要么不返回結果,這取決于用戶訪問的行是否是相關行。請看下面的函數:

CREATE FUNCTION Security.fn_securitypredicate(@SalesRep AS sysname) RETURNS TABLE WITH SCHEMABINDING AS RETURN SELECT 1 AS fn_securitypredicate_result WHERE @SalesRep = USER_NAME() OR USER_NAME() = 'Manager'; 

這段代碼的意思是,當前用戶必須是一名經理,或者是一名與記錄相關的推銷員。該函數沒有訪問行本身,但用戶可以使用參數傳入相應的列(比如,SalesRep)。例如:
CREATE SECURITY POLICY SalesFilter ADD FILTER PREDICATE Security.fn_securitypredicate(SalesRep) ON dbo.Sales WITH (STATE = ON); 

實際效果

在使用行級安全時,用戶無法看到他們不能訪問的行。這就好像在訪問表時自動增加一個額外的、安全相關的where子句。

由于其作用像一個where子句,所以有一些局限。例如,如果用戶在那個列上使用了全文搜索索引,那么數據就可能泄露。此外,數據庫還可能遭受旁路攻擊。微軟寫道:

通過使用精心設計的查詢,可以導致信息泄露。例如,SELECT 1/(SALARY-100000) FROM PAYROLL WHERE NAME='John Doe' 會讓一個惡意用戶知道John Doe的工資是10萬美元。即使有一個恰當的安全謂詞阻止惡意用戶直接查詢其它人的工資,他也可以在查詢返回“除數為0”的異常時確定工資數額。

此外,信息也可能通過統計對象泄露。為了降低風險,查看受保護列統計信息的用戶必須是“表的所有者,或者是服務器固有角色sysadmin、數據庫固有角色db_owner或db_ddladmin的成員”。

中間層應用程序

截至目前,我們討論的場景是用戶以自己的身份登錄。在中間層應用程序中,所有人都共享同一個數據庫賬戶,實現行級安全需要額外的步驟。

對于中間層應用程序,推薦的設計模式是將 CONTEXT_INFO 的值設置為連接打開時用戶特定于應用程序的用戶id。然后,安全函數就可以引用CONTEXT_INFO的值。例如:

CREATE FUNCTION Security.fn_securitypredicate(@AppUserId int) RETURNS TABLE WITH SCHEMABINDING AS RETURN SELECT 1 AS fn_securitypredicate_result WHERE DATABASE_PRINCIPAL_ID() = DATABASE_PRINCIPAL_ID('dbo') -- 應用程序上下文 AND CONVERT(int, CONVERT(VARBINARY(4), CONTEXT_INFO())) = @AppUserId; -- AppUserId (int)占4個字節 GO CREATE SECURITY POLICY Security.SalesFilter ADD FILTER PREDICATE Security.fn_securitypredicate(AppUserId) ON dbo.Sales WITH (STATE = ON); 

該方法的前提是,用戶無法執行任意SQL,因為那會讓他們可以隨意更改CONTEXT_INFO。

查看英文原文: SQL Server 2016: Row-Level Security

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!