呼叫 Web 服務的 SQLCLR TVF 出現錯誤 401:未經授權
我正在從 SQL Server 2008 R2 中的 SQLCLR TVF 呼叫 Web 服務。
在 IIS 伺服器上,此服務具有打開權限。在瀏覽器上使用 GET 或 POST 請求進行測試時,Web 服務按預期工作。但是,當函式呼叫服務時,它會返回:
請求失敗,HTTP 狀態為 401:未授權。
以典型的軼事方式,當我在我的機器上執行 TVF 以訪問我機器上的服務時,它可以工作。(證明程式碼正確)
當使用網路上的 SQL Server 訪問網路上的另一個 ISS 伺服器時,會發生此錯誤。兩台伺服器都在同一個域中。
如何確定阻止此 TVF 工作的缺失權限?
幾個基本的 SQL Server 檢查:您的數據庫是否設置為值得信賴?程序集是否設置為允許 UNSAFE 執行?
如果這似乎有效,那麼網上有一些教程可能會有所幫助。如果那裡的教程都沒有幫助,那麼聽起來像是權限問題。(不幸的是,這變得很棘手,因為討論 Kerberos 與 NTLM 身份驗證的執行緒顯示。)
另一項檢查——正如 Maumen 提到的——確保您為 IIS 設置了匿名訪問。
但最終,如果可以的話,這聽起來像是你想要避免的事情。性能和記憶體影響、讓所有帳戶正常工作的困難以及降低所有安全設置會讓我有點緊張。
鑑於錯誤發生在外部服務(即 IIS)中,問題不在於您的程序集的安全級別。如果它是
PERMISSION_SET
Assembly 的,您將獲得一個 .NETSecurityException
類型的 .NETWebPermission
。根據 OP 對這個問題的評論,我們知道:
服務帳戶是域帳戶。TVF 正在使用呼叫者的身份來執行 Web 服務。
確定“呼叫者的身份”並不是那麼簡單。
首先,這可能是指語句的
EXECUTE AS
子句CREATE FUNCTION
,暗示它被設置為CALLER
(通常是這樣)。這將是必要的,但它本身不會使 SQLCLR 對像中的外部呼叫採用正在執行 SQLCLR 對象的 Windows 登錄的身份。其次,有憑據可以傳遞給
WebClient
/HttpRequest
對象。如果將UseDefaultCredentials屬性設置為 true,則可能會認為在 SQL Server 中執行程式碼的登錄應該被傳遞,尤其是該屬性上的註釋說明請求將“使用目前登錄使用者的預設憑據進行身份驗證” . 但是,預設情況下,由 SQL Server 中的 CLR 主機執行的所有請求都是使用執行 MSSQLSERVER 服務的服務帳戶的安全上下文進行的(如果是預設實例,則為 MSSQL$InstanceName 之類的東西)。第三,為了讓外部操作的安全上下文成為執行SQLCLR對象的Login,需要使用Impersonation。這需要
WindowsIdentity
從 the獲取SqlContext
並呼叫Impersonate方法(完成後,您將需要呼叫Undo()
thenDispose()
)。如果不能按預期工作,可能是由於該
UseDefaultCredentials
屬性的另一部分註釋:對於中間層應用程序(例如 ASP.NET 應用程序),通常不使用此屬性,而是將Credentials屬性設置為代表其發出請求的客戶端的憑據。
在這種情況下,您可能想嘗試按照建議設置憑據。
或者,如果您正在使用 Impersonation 並且
UseDefaultCredentials
仍然面臨此錯誤,請給出以下資訊:當使用網路上的 SQL Server 訪問網路上的另一個 ISS 伺服器時,會發生此錯誤。
您很可能會遇到臭名昭著的雙跳身份驗證問題,該問題已經浪費了很多個小時(尤其是在涉及連結伺服器時)。當一個真實的人或服務(例如 IIS)登錄到機器 A 並使用可信連接/集成安全性連接到機器 B 上的 SQL Server 時,就會發生這種情況。那是第 1 跳(因為人或服務沒有直接向機器 B 提供憑據/密碼)。然後,剛剛連接到機器 B 上的 SQL Server 的同一個 Windows 登錄嘗試連接到機器 C,再次使用受信任的連接/集成安全性。這將是第 2 跳。預設情況下,不允許第 2 跳,這很可能是因為從安全形度來看,它的風險更大,因為與機器 C 的連接源是機器 B,它實際上只是真實登錄事件的代理發生在機器 A 上。
- 使用 Kerberos 身份驗證
- 設置所需的 SPN。
- 如果這不起作用,則在 Active Directory 中,為應該能夠從 SQL Server 呼叫 Web 服務的登錄名啟用“委託”。
您應該能夠使其工作,而無需將 Web 服務配置為允許匿名訪問。