使用 SQL CLR 的安全或性能風險
在 SQL Server 中使用 CLR 是否存在任何特定的安全或性能風險?
正如 Remus 指出的那樣,這個問題太籠統而無法得到答案,因為答案取決於要使用什麼功能以及如何使用它的上下文。
關於“安全”:
如果您要詢問可以在標有 的程序集中完成的任何事情
PERMISSION_SET = SAFE
,那麼我找不到任何問題。而且 SQLCLR 比使用xp_cmdshell
或美妙的(那是諷刺的)sp_OA*
過程(甚至是擴展儲存過程,但希望沒有人再創建任何這些過程)“更安全”。如果您想了解“SAFE”的實際含義,請參閱這篇文章:SQLCLR 級別 3 的階梯:安全性(正常和 SAFE 程序集)(需要免費註冊)。
如果您詢問可以在標有 的程序集中完成的任何事情
PERMISSION_SET = EXTERNAL_ACCESS
,那麼肯定存在風險,再次取決於正在使用的功能。如果您編寫一個常式來讀取目錄和文件名(即只讀),那麼這只是應該看到什麼和不看到什麼的問題。如果您正在編寫允許刪除文件的程式碼,則風險會增加。但是可以用這些外部資源做什麼是由以下控制的:
無論您是否使用模擬:
- 沒有模擬意味著訪問外部資源是通過 SQL Server 服務的“登錄身份”帳戶完成的。無論該帳戶有權訪問什麼,您的 SQLCLR 函式都可以執行此操作。
- 使用模擬意味著執行該函式的 SQL Server 中的登錄名,如果該登錄名對應於 Windows 登錄名,則可以執行該特定 Windows 登錄名允許執行的任何操作。如果 SQL Server 中的登錄名是 SQL Server 登錄名,則嘗試使用 Impersonation 會出錯。
對外部資源設置了哪些權限。對於文件系統訪問,這是通過 NTFS 驅動器上的 ACL 控制的。
如果您要詢問可以在標記為的程序集中完成的任何事情
PERMISSION_SET = UNSAFE
,這是相當開放的。許多功能被認為只能在 UNSAFE 程序集中使用,因為它們是穩定性和/或一致行為的問題,而不是安全性或性能問題。例如,在 UNSAFE 程序集中,可以有一個可寫的靜態變數。這通常不是一件好事,因為 SQLCLR 類在所有會話中共享。如果您的意圖是在所有會話中共享記憶體中的數據併計劃競爭條件(並完成大量測試),那麼您應該沒問題,因為您期望這種行為。但是,如果您只是想要一個可寫的靜態變數來記憶體特定會話的值,而不必再次查找或計算它,並且不知道其他會話正在讀取該值並可能覆蓋它,那麼,那將是一個問題。但是,如果您擔心有人寫入系統資料庫,但沒有任何實際寫入系統資料庫的程式碼,那麼您可能不需要擔心這個;-)。
如果您想了解 EXTERNAL_ACCESS 和 UNSAFE 的實際工作原理,以及設置
TRUSTWORTHY ON
(非首選)與使用基於非對稱密鑰或證書的登錄之間的區別,請參閱這篇文章:SQLCLR 級別 4 的階梯:安全性(外部和不安全組件)(需要免費註冊)。關於“性能”:
這完全取決於您要做什麼以及如何去做。在 SQLCLR中有些事情要快得多,有些事情要慢得多。但就像 T-SQL 一樣,有可能採取一些簡單和/或高效的任務,並通過錯誤地做事使其變得複雜和/或低效。但是,就其本質而言,使用 SQL CLR 並不是天生就比較慢。
SQLCLR 程序集可以安裝三個級別的安全訪問:
SAFE | EXTERNAL_ACCESS | UNSAFE
. 這有充分的記錄,請參閱CREATE ASSEMBLY
和設計程序集:管理程序集安全性
您可以控製程序集在執行託管程式碼時可以訪問多少受 .NET 程式碼訪問安全性保護的資源。您可以通過在創建或修改程序集時指定三個權限集之一來執行此操作:SAFE、EXTERNAL_ACCESS 或 UNSAFE。
SAFE
SAFE 是預設權限集,也是最嚴格的。由具有 SAFE 權限的程序集執行的程式碼無法訪問外部系統資源,例如文件、網路、環境變數或系統資料庫。SAFE 程式碼可以訪問本地 SQL Server 數據庫中的數據,或者執行不涉及訪問本地數據庫外部資源的計算和業務邏輯。
大多數程序集執行計算和數據管理任務,而不必訪問 SQL Server 之外的資源。因此,我們推薦 SAFE 作為組裝權限集。
EXTERNAL_ACCESS
EXTERNAL_ACCESS 允許程序集訪問某些外部系統資源,例如文件、網路、Web 服務、環境變數和系統資料庫。只有具有 EXTERNAL ACCESS 權限的 SQL Server 登錄才能創建 EXTERNAL_ACCESS 程序集。SAFE 和 EXTERNAL_ACCESS 程序集只能包含可驗證類型安全的程式碼。這意味著這些程序集只能通過對類型定義有效且定義明確的入口點來訪問類。因此,它們不能任意訪問不屬於程式碼的記憶體緩衝區。此外,它們不能執行可能對 SQL Server 程序的穩健性產生不利影響的操作。
UNSAFE
UNSAFE 使程序集可以不受限制地訪問 SQL Server 內部和外部的資源。從 UNSAFE 程序集中執行的程式碼可以呼叫非託管程式碼。此外,指定 UNSAFE 允許程序集中的程式碼執行 CLR 驗證程序認為類型不安全的操作。這些操作可能以不受控制的方式訪問 SQL Server 程序空間中的記憶體緩衝區。UNSAFE 程序集還可能破壞 SQL Server 或公共語言執行時的安全系統。UNSAFE 權限應僅由經驗豐富的開發人員或管理員授予高度信任的程序集。只有 sysadmin 固定伺服器角色的成員才能創建 UNSAFE 程序集。
對允許的 CLR 屬性有進一步的限制,並且僅支持 .Net Framework 程序集的一個子集。同樣,請參閱連結的文件。
至於性能,最重要的是要記住 SQL Server 是一個協作多任務環境,而 CLR 不是。SQLCLR 程式碼必須
Thread.BeginThreadAffinity()
在任何時間(包括阻塞)佔用 CPU 的任何時間呼叫。Adam Machanic 就該主題進行了出色的展示,請觀看Data, Faster: Microsoft SQL Server Performance Techniques with SQLCLR。話題很大,問題也很模糊。SQLCLR 可以執行一些其他功能無法比擬的獨特任務。SQLCLR 只是 SQL Server 武器庫中的另一種武器,無論是性能還是安全性,您都可以用它來打自己的腳。閱讀文件。