在创建SQL Server CLR存储过程时,我注意到我无法正常引用.net框架中的任何内容。经过一番阅读后,我意识到需要先将程序集加载到数据库中。
因此,我加载了我需要的,但由于P / Invoke必须使用UNSAFE权限集。我现在可以在我的存储过程代码中引用它们,一切正常。
然而,当我不知道他们在做什么时,我有点担心必须将它们设置为UNSAFE。所以我的问题是:
是否可以将.net框架作为UNSAFE加载而不完全正在做什么? 如何这样做会破坏sql server的安全性/健壮性/可伸缩性(正如微软警告它可能的那样)?
非常感谢。
答案 0 :(得分:2)
它可以更改注册表,重新启动服务,重新启动服务器等。没什么太重要的;-)一个简单的chart with the differences
也可以看到这个问题(虽然没有答案)SQL Server 2008: How crash-safe is a CLR Stored Procedure that loads unmanaged libraries
当然,你在做什么需要UNSAFE访问?
答案 1 :(得分:0)
当您在托管许多公共网站的服务器上使用SQL数据库引擎时,您不了解作为服务器管理员(或DBA或负责任何人)的任何信息,您应该限制他们的访问并且该死的#&# 39;重要!此外,如果您在限制区域拥有DBA,数据在某些大公司中最为重要,那么它也是最重要的事情。
在我看来,你应该提供你需要看到的应用程序,仅此而已。例如,如果您不需要查看注册表,为什么要对程序集进行不受限制的访问?你不知道如果有人注入你的应用程序的代码并劫持数据库(也有不受限制的访问权限,那么它会有多危险。)。
希望有所帮助
答案 2 :(得分:0)
此问题特定于加载不在Supported .NET Framework Libraries集合中的.Net Framework程序集,因此我将重点介绍Microsoft提供的DLL而不是任何随机DLL的上下文。
"支持"中的组件之间的差异;列表和不在列表中的列表归结为受支持的列表已经过测试,以确保它们符合与SQL Server交互的可靠性和安全性标准。 (如"支持的库"上面链接的页面中所述)。主要问题更多的是"可靠性"而不是"安全"。受支持列表中的程序集已经过验证,其行为符合预期,并且没有任何错误或奇怪的副作用。该功能已经过测试,可以使用各种语言和校对等。
某些不在受支持列表中的.Net Framework程序集可以加载PERMISSION_SET
设置为SAFE
。然而,这并不能保证所期望的行为。有些可以加载为UNSAFE
,但不一定表明会出现问题。
作为不保证行为的示例:我已经加载System.Drawing
以便进行一些简单的图像处理。我通过byte[]
/ VARBINARY(MAX)
直接提供图像以及文件路径提供图像并从磁盘读取时测试了操作。一切都按预期工作。我把它发送给德国的某个人,他们的Windows和SQL Server都被设置为"德语"作为语言。在直接提供图像时,他能够获得预期的结果。但是当他提供文件路径时,它没有用。
对于不受欢迎的行为,SQL Server将显示当您尝试执行此操作时,程序集无法加载SAFE
或EXTERNAL_ACCESS
的原因。例如:
CREATE ASSEMBLY [System.Drawing]
AUTHORIZATION [dbo]
FROM 'C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.Drawing.dll'
WITH PERMISSION_SET = SAFE;
结果:
警告:Microsoft .NET Framework程序集&system;抽象,版本= 4.0.0.0,culture = neutral,publickeytoken = b03f5f7f11d50a3a,processorarchitecture = msil。'您正在注册未在SQL Server托管环境中进行全面测试,并且不受支持。将来,如果升级或维护此程序集或.NET Framework,则CLR集成例程可能会停止工作。有关更多详细信息,请参阅SQL Server联机丛书。
Msg 6218,Level 16,State 2,Line 1
为汇编' System.Drawing'创建汇编。失败,因为汇编' System.Drawing'验证失败。检查引用的程序集是否是最新的并且在数据库中是否可信(对于external_access或unsafe)。 CLR Verifier错误消息(如果有的话)将跟随此消息[:System.Drawing.BufferedGraphicsContext :: bFillColorTable] [mdToken = 0x600013c] [offset 0x00000053] [找到字节的地址]堆栈上的预期数字类型。
[:System.Drawing.BufferedGraphicsContext :: bFillColorTable] [mdToken = 0x600013c] [offset 0x00000043] [找到Native Int] [字节的预期地址]堆栈上的意外类型。
[:System.Drawing.BufferedGraphicsContext :: bFillColorTable] [mdToken = 0x600013c] [offset 0x00000027] [找到Native Int] [字节的预期地址]堆栈上的意外类型。
[:System.Drawing.Icon :: ToBitmap] [mdToken = 0x6000349] [offset 0x00000084] [找到非托管指针] [预期的非托管指针]堆栈上的意外类型。
[:System.Drawing.Icon :: ToBitmap] [mdToken = 0x6000349] [offset 0x000000E4]非托管指针不是可验证的类型。
[:System.Drawing.Icon :: GetShort] [mdToken = 0x6000356] [offset 0x00000002]非托管指针不是可验证的类型。
...
如果您不打算使用任何这些方法或类型,那么您可能不会遇到任何问题。没有办法将" safe"来自"不安全的东西"项目
另一个内疚关联的例子是:
CREATE ASSEMBLY [System.Web]
AUTHORIZATION [dbo]
FROM 'C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.Web.dll'
WITH PERMISSION_SET = SAFE;
结果:
警告:Microsoft .NET Framework程序集' system.web,版本= 4.0.0.0,culture = neutral,publickeytoken = b03f5f7f11d50a3a,processorarchitecture = x86。'您正在注册未在SQL Server托管环境中进行全面测试,并且不受支持。将来,如果升级或维护此程序集或.NET Framework,则CLR集成例程可能会停止工作。有关详细信息,请参阅SQL Server联机丛书。
警告:Microsoft .NET Framework程序集' microsoft.build.framework,版本= 4.0.0.0,culture = neutral,publickeytoken = b03f5f7f11d50a3a,processorarchitecture = msil。'您正在注册未在SQL Server托管环境中进行全面测试,并且不受支持。将来,如果升级或维护此程序集或.NET Framework,则CLR集成例程可能会停止工作。有关详细信息,请参阅SQL Server联机丛书。
警告:Microsoft .NET Framework程序集' system.xaml,版本= 4.0.0.0,culture = neutral,publickeytoken = b77a5c561934e089,processorarchitecture = msil。'您正在注册未在SQL Server托管环境中进行全面测试,并且不受支持。将来,如果升级或维护此程序集或.NET Framework,则CLR集成例程可能会停止工作。有关详细信息,请参阅SQL Server联机丛书。
Msg 6212,Level 16,State 1,Line 1
CREATE ASSEMBLY失败,因为方法' TypeDescriptorRefreshed' on type' System.Windows.Markup.ValueSerializer'在安全组装和System.Xaml'正在存储到静态字段。安全组件中不允许存储到静态字段。
正如您所看到的,System.Web
实际上对SAFE
来说很好,但它具有依赖程序集并且正在自动加载。第一个依赖程序集microsoft.build.framework
也没有问题(至少没有问题可以验证,尽管有SAFE
中不允许的内容可能存在,但只能在运行时捕获) 。但是第二个依赖程序集确实存在一个问题,可以在加载程序集时进行验证:它是存储到静态字段"。这对于可靠性而不是安全性是一个问题,因为类被实例化一次(好吧,每个App Domain,意思是:每个数据库,每个所有者)并在SPID之间共享以使用(这就是为什么在SQLCLR中只能访问静态方法) 。因此,静态类级变量在技术上在会话(即SPID)之间共享信息,并且很容易导致意外行为。但与此同时,如果您只想使用HtmlString.ToHtmlString()
,那么您可能无法使用System.Xaml
。那么为什么不将System.Web
加载为SAFE
而将System.Xaml
加载为UNSAFE
呢?可能是因为SAFE
程序集中的代码不允许调用UNSAFE
程序集中的代码(至少不在SQLCLR中)。
<强> CONLUSION 强>
那么加载UNSAFE
.Net Framework程序集是否可以?这真的应该归结为测试。大量测试(不仅仅是开发盒上的单个线程,而是真正的测试)。如果一切都像预期的那样,那么你应该没问题。但是,如果某些内容没有按预期运行,那么不是一个可以向Microsoft报告的错误,因为它已经被声明为不受支持。
修改强>
以下是对此问题的更正式回答,其中列出了可能出现问题的几种情况:Support policy for untested .NET Framework assemblies in the SQL Server CLR-hosted environment