http://www.iloveyou10000.com

新blogs地址 http://itares.cnblogs.com

博客园 首页 新随笔 联系 订阅 管理
二、 访问外部资源

因为访问外部资源需要与操作系统进行交互,所以,当代码尝试存取外部的资源时,存在多种要遵守的规则。

对于SAFE代码来说,这种规则是简单的:如果它试图存取一个外部的资源,那么存取将被否认并且它引发一个异常。就是这些。

对于EXTERNAL_ACCESS和UNSAFE的情况,则复杂些:

· 规则1:如果代码在一个SQL Server登录的安全上下文下执行(也就是说,还没有被映射到一个Windows用户或组),那么存取将被禁止并且引发一个异常。一个SQL登录并不拥有SQL Server外的任何许可权,因此这是很重要的。

· 规则2:如果代码在一个被映射到一个Windows登录的登录下执行,那么进行外部存取的执行上下文就是该登录的执行上下文。如果该用户能够存取Windows中的资源,那么该代码成功。如果不是,存取被否认并且引发一个异常。

· 规则3:如果调用者不是原始的调用者(已经进行了一个执行上下文切换),那么存取被否认并且引发一个异常。

一开始,这些规则也使我有点糊涂,但是,当我以后逐渐地越来越多地使用它们时,它们开始变得很重要了。对于规则1来说,因为一个SQL登录仅仅存在于 SQL Server世界中,所以,如果它能存取操作系统资源的话,这将是一个巨大的安全漏洞。规则2也很重要,并且它允许模拟。规则3似乎有点严格,但是我怀疑 SQL Server小组有点保守,因为上下文切换可能会是一场"管理恶梦",并且他们仍然确信不会产生安全漏洞问题。

外部的存取规 则甚至更复杂些。假定运行代码的登录已经成功"越过"上面列举的"重重封锁",但是,为了存取外部的资源-正如你可能盼望的(并且也许希望),SQL Server并不自动地模拟当前执行上下文。代之的是,它使用SQL Server实例的服务帐户来存取资源。或者,你也可以显式地模拟上下文登录来存取资源。这样做需要使用SqlContext对象的 WindowsIdentity属性来调用WindowsIdentity来实现实际的模拟。

列表1:在SQLCLR代码中使用模拟

try
{
//模拟当前SQL安全上下文
WindowsIdentity CallerIdentity = SqlContext.WindowsIdentity;
if (CallerIdentity != null)
{
OriginalContext = CallerIdentity.Impersonate();
//做一些保护操作
}
}
catch
{
//从存取问题中恢复
}
finally
{
if (OriginalContext != null)
OriginalContext.Undo();
}

列表1向你展示如何在SQLCLR代码中使用模拟。WindowsImpersonationContext对象属于 System.Security.Principal命名空间的一部分并且描述了在你模拟前的Windows用户安全上下文。SqlContext对象属 于和SQL Server一起安装的Microsoft.SQL Server.Server命名空间的一部分并且提供在SQL Server主机和SQLCLR代码之间的一个钩子。在这种情况中,它使用WindowsIdentity属性来得到当前安全身份的一个令牌。这是 Windows登录的安全上下文-该代码在这一登录下运行。该代码测试是否结果CallerIdentity为null,如果该代码在一种SQL登录下运 行时它将为null。最后,它调用WindowsIdentity模拟来实现实际的模拟,并保存原始的上下文以用于当要求恢复到该上下文时。

必须理解,仅当执行需要保护的操作(例如打开一文件)时模拟才起作用。一旦它被打开,该代码就不再需要模拟。因此,一旦你完成保护的操作,即恢复回去。

最后,通过调用OriginalContext的Undo方法,代码块负责恢复到原始上下文。如果你在函数结束之前不进行恢复,那么SQL Server将引发一个异常。

对于模拟也存在一些限制。当该模拟起作用时,你就无法再使用SQL Server实例存取数据或对象。在你再次存取本地数据之前,你必须恢复模拟。这也意味着,进程内数据存取总是发生在会话的当前安全上下文中。

有趣的是,一个异步执行的UNSAFE程序集(也就是说,它能够创建线程并且异步地运行代码)永远不会允许进程内数据存取。其实,这并不是一个安全问题而显然是一个可靠性的问题。

三、 可信赖的数据库

在SAFE程序集和其它权限设置级别之间的另外一个区别是在SQL Server 2005测试期添加的。现在,你必须满足两个要求之一来创建EXTERNAL_ACCESS或UNSAFE程序集:

· 数据库所有者(dbo)必须拥有EXTERNAL ACCESS ASSEMBLY权限并且数据库必须拥有TRUSTWORTHY属性集。

或者:

· 程序集的使用方式必须是,通过一个具有EXTERNAL ACCESS ASSEMBLY权限的登录而且要使用一个证书或一个非对称密钥。

EXTERNAL ACCESS ASSEMBLY权限是另一种新的粒度许可权-允许一名负责人创建这类程序集。默认情况下,系统管理员拥有它并且能够把它赋给其它登录。但是这样做时要慎重,这当然因为可能潜在地允许危险代码安装到服务器中。

一个数据库的TRUSTWORTHY属性要求设置管理员权限并且是在数据库中安装非SAFE程序集的前提。基于EXTERNAL ACCESS ASSEMBLY权限,一个DBA能够控制是否存在潜在危险性的程序集能够被安装到任何数据库中,以及谁能够把它们放到那里。这很有希望会使DBA安心而 不必再担心他们的服务器会感染.NET代码!
posted on 2007-10-15 09:35  fanrsh  阅读(592)  评论(0编辑  收藏  举报