Sql-Server

使用非對稱密鑰的具有 UNSAFE 或 EXTERNAL_ACCESS 權限的程序集部署

  • December 3, 2018

當我們嘗試使用 PERMISSION_SET=UNSAFE 或 EXTERNAL_ACCESS 部署程序集時,SQL Server 收到以下錯誤消息:

CREATE ASSEMBLY for assembly 'System.ServiceModel.Internals' failed because 
assembly 'System.ServiceModel.Internals' is not authorized for 
PERMISSION_SET = UNSAFE.  The assembly is authorized when either of the 
following is true: the database owner (DBO) has UNSAFE ASSEMBLY permission 
and the database has the TRUSTWORTHY database property on; or the assembly 
is signed with a certificate or **an asymmetric key that has a 
corresponding login with UNSAFE ASSEMBLY permission.**

我們沒有設置數據庫可信任=ON,而是使用 ALGORITHM = RSA_2048 創建非對稱密鑰。以下是範常式式碼:

USE master; 
GO  

IF NOT EXISTS (SELECT 1 FROM sys.asymmetric_keys WHERE [name]='SampleClrKey')
BEGIN
     CREATE ASYMMETRIC KEY [SampleClrKey] WITH ALGORITHM = RSA_2048
     CREATE LOGIN [SampleClrLogin] FROM ASYMMETRIC KEY [SampleClrKey];  
     GRANT UNSAFE ASSEMBLY TO [SampleClrLogin];
END
GO

但是這個錯誤沒有得到解決。我什至為我的數據庫和主數據庫提供了對 SampleClrLogin 登錄的系統管理員訪問權限,但它不起作用。你們能否提供一些見解來解決這個問題。

問題是您正在 SQL Server 中創建一個隨機的新非對稱密鑰,它不會將登錄名關聯到程序集,這就是非對稱密鑰(或證書)的用途。

在將程序集載入到 SQL Server 之前,您需要*先對其進行簽名。*無論是使用強名稱密鑰(相當於 SQL Server 中的非對稱密鑰)還是證書進行簽名,您都可以在其中創建相同的非對稱密鑰或證書(僅需要公鑰)master,然後創建基於簽名的登錄從此。

有關如何完成此操作的範例(以及可以通過 Visual Studio / SSDT 自動化的方式),請參閱我正在編寫的關於使用 SQLCLR(在 SQL Server Central 上)的系列:Stairway to SQLCLR(第 7 級和第 8 級)特定)。

如果您使用的是 SQL Server 2017 或更高版本,則需要考慮一個額外的複雜問題,這不是 SQL Server 中心文章中描述的方法的一部分。為此,請參閱我的文章中修改後的方法的兩個選項:

PS 感謝您花費額外的幾分鐘來啟用 TRUSTWORTHY :-)


澄清

由於您正在嘗試載入不受支持的 .NET Framework 庫,因此您不會自己編譯,因此我上面概述的步驟在這裡不起作用(儘管它們仍然與某些人簡單地誤解並嘗試在最初創建非對稱密鑰相關SQL Server 如問題所示)。

但是,鑑於:

  1. 您正在嘗試載入System.ServiceModel.Internals而不是System.ServiceModel,並且
  2. 沒有收到有關特定庫“格式錯誤或不是純 .NET 程序集”的錯誤

那麼您可以通過執行以下操作來完成此操作(同時保持TRUSTWORTHY OFF!):

USE [master];
CREATE CERTIFICATE [UnsupportedFrameworkLibraryPermissions]
 FROM EXECUTABLE FILE =
 'C:\Windows\Microsoft.NET\Framework64\v4.0.30319\System.ServiceModel.Internals.dll';

CREATE LOGIN [UnsupportedFrameworkLibraryPermissions]
 FROM CERTIFICATE [UnsupportedFrameworkLibraryPermissions];

GRANT UNSAFE ASSEMBLY TO [UnsupportedFrameworkLibraryPermissions];

進而:

USE [{your_DB_name_here}];

CREATE ASSEMBLY [System.ServiceModel.Internals]
 FROM 'C:\Windows\Microsoft.NET\Framework64\v4.0.30319\System.ServiceModel.Internals.dll'
 WITH PERMISSION_SET = UNSAFE;

請記住,此技術不適用於System.ServiceModel.dll. 該庫從純 MSIL pre-.NET 4.0 變為混合在 .NET 4.0 中,並且只有純 MSIL 庫可以載入到 SQL Server 中。使用在 SQL Server 2005、2008 和 2008 R2 中有效,因為這些版本使用與純 MSILServiceModel的 .NET Framework 版本 2.0、3.0 和 3.5 相關聯的 CLR 2.0 。ServiceModel

但總的來說,David Browne 是正確的,因為您可能應該使用它HttpWebRequest(取決於您需要System.ServiceModel.Internals的用途)。

System.ServiceModel.Internals

你可以在那裡停下來。WCF 不能在 SQL CLR 中使用。SQL CLR 僅支持純 MSIL 程序集,.NET 4.x 中的 WCF 引用了一些混合模式程序集。

請參閱無法註冊不在支持列表中的 .NET 框架程序集

https://stackoverflow.com/questions/40349838/sql-server-2016-create-assembly-for-assembly-system-servicemodel-failed

如果您從 SQL CLR 呼叫 Web 服務,則可以使用WebClient API或較低級別的HttpWebRequest,這兩者都在 System.dll 中實現。

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