在很多场景中,都会有多个数据库对象一个接着一个互相访问的情况出现。一个例子就是,一个存储过程调用了一个视图,接下来,调用了一个表。当这种情况出现的时候,SQL Server需要评估被参考对象的权限。它处理的方式与那种那些同样的对象被直接访问所采用的方式不太一样。这样的安排被称为所有权链。理解它们的工作方式很重要,如果你在一个不是每个人对每个对象都拥有相同的访问权的环境,使用一种类型的对象去访问另一种类型的对象,当然这种环境是理所应当的。
对于所有权链有三个基本规则:
1、如果你访问某个对象,然后通过它参考了另外一个对象(例如访问表的视图),那么这两个对象都有同样的所有者,在第二个对象上的权限就不被检验了。如果你访问了第一个项目,那么它假设你已经访问了第二个。
2、如果你访问某个对象,然后通过它参考另外一个对象,但是第二个对象却没有相同的所有者,那么就需要检查检索者对第二个对象的权限。如果用户没有允许访问第二个对象的权限,它就不能读取它了。
3、所有这些都是在调用了最初对象的用户的安全上下文中出现。如果用户没有访问最初的对象,就什么事情也不会发生(这才是标准的安全实践)。
只有一个关键的例外情况,这些规则不管对象的被访问类型。如果你通过链链接到了同一个SQL Server实例中的另外一个数据库中的对象身上去,那么这个规则不起作用。这种类型的访问就是跨数据库所有权链(CDOC)。默认情况下,SQL Server中是关闭这个特性的,因为这种方法作为防御一个可以本地访问并且蓄意犯罪的人的方式,实在是太简单了,以至于没有什么用处。
SQL Server 2005中有一些新的特性,使得工作在跨数据库,或者不同所有者的对象之间,并且不需要明确的授予访问权限或者使用CDOC,成为可能。例如,如果你使用CDOC来允许一个存储过程的跨数据库的访问,你可能会使用类似Service Broker之类的东西来完成这件事情。或者,你还可以在另外的数据库中创建一个可以安全处理此类事件的匹配的存储过程。
SQL Server 2005中的所有权链的使用方式的另一个改变就是调用EXECUTE AS子句,它可以让你在另一个用户的环境中运行许多操作。它只能被那些拥有扮演其他用户角色权限的人使用,例如,系统管理员。虽然在执行过程中权限的检查会让你选择使用哪个身份,但是它并不强制检查(但是这里有一种例外情况,我曾见到过)。
EXECUTE AS的用处很多。首先,它可以让你轻松评估(其他活动环境中)某个用户是否可以访问链中的某个东西。这是考虑到所有链经常被理所当然地使用的情况的一个重要功能。因为链工作的方式,它并不总是十分明显地表现出你可以(或者不可以)访问某个相关的对象,因此每当可能使用EXECUTE AS的时候对对其进行审计是个好主意。它在限制用户的环境中运行一个具有潜在危险的操作的时候,也是非常有用的方式。另一个好处就是,如果你创建了使用了EXECUTE AS的存储过程,你可以更加精确地定义存储过程运行的安全环境。
此外,EXECUTE AS可以通过使用EXECUTE AS SELF来强制打破所有链。例如,如果你在存储过程的环境中使用了EXECUTE AS SELF, 那么这个存储过程对任何底层对象的访问权限都会被显式地检查。这样的事情可以放声在多个层次上,包括当你调用一个调用了其他存储过程的存储过程的时候,例如,在链中的某个地方使用了EXECUTE AS SELF。
注意,如果SQL Server是在本地账户中运行的话,EXECUTE AS就不起作用了。当它以本地账号的身份建立起来的时候,它不能Windows域内账号的读取组成员。如果你恰好安装的是SQL Server桌面引擎,并且出于安全的原因使用了本地账号,那么小心了。