Sql-Server

呼叫 Web 服務的 SQLCLR TVF 出現錯誤 401:未經授權

  • October 7, 2016

我正在從 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_SETAssembly 的,您將獲得一個 .NETSecurityException類型的 .NET WebPermission

根據 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()then Dispose())。

如果不能按預期工作,可能是由於該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 上。

  1. 使用 Kerberos 身份驗證
  2. 設置所需的 SPN。
  3. 如果這不起作用,則在 Active Directory 中,為應該能夠從 SQL Server 呼叫 Web 服務的登錄名啟用“委託”。

您應該能夠使其工作,而無需將 Web 服務配置為允許匿名訪問。

引用自:https://dba.stackexchange.com/questions/3462