微软BI开拓者数据库专区SQL Server管理 理解SQLServer里的跨数据库所有权链

1  /  1  页   1 跳转 查看:1217

[技术文档] 理解SQLServer里的跨数据库所有权链

理解SQLServer里的跨数据库所有权链

理解SQLServer里的跨数据库所有权链

--王成辉翻译整理,转贴请注明出自微软BI开拓者www.windbi.com
--原帖地址

问题

我已经理解了所有权链,但我还是不懂跨数据库所有权链是什么,它是如何运作的。所有者是怎样决定跨数据库的,所有权是基于数据库用户的吗?


解决方法


跨数据库所有权链是所有权链的一个扩展,只是它跨越了数据库界限。如果你还不熟悉所有权链,你可以去点击这里进行查看。如果在一个数据库里有一个视图,而它引用了另一个数据库里的表,那么就会发生跨数据库所有权链。第一个数据库里的视图引用了第二个数据库里的表。如果我们正讨论的对象在同一个数据库里,并且表和视图的所有者是同一个用户,那么就形成了所有权链,此时用户仅需访问视图即可。对于跨数据库所有权链,此种事情也可能发生,只不过是跨数据库而已。


跨数据库所有权链可以在服务器级或数据库级打开。如果跨数据库所有权链在服务器级打开的话,那么它就对服务器上所有的数据库是打开的,而不管单独的数据库设置是什么。默认情况下,跨数据库所有权链在服务器级是关闭的,并且除了以下数据库外的其他数据库上也是关闭的:


  • master
  • msdb
  • tempdb
有3个系统数据库要求跨数据库所有权链要打开。除了这3个外,由于安全方面的因素,通常规则如下:
  • 跨数据库所有权链应该在服务器级上打开
  • 应该仅打开所需数据库上的跨数据库所有权链。

你可以用下面的查询(适用于SQLServer2005/2008)来查看跨数据库所有权链是否在服务器级打开。如果值是0,就是关闭的,是1则是打开的。


SELECT [name], value 
FROM [sys].configurations
WHERE [name] = 'cross db ownership chaining';



这也适用于sys.databases的列db_chaining_on。我们可以查询sys.databases来看看哪些数据库的跨数据库所有权链是明确打开的:


SELECT [name] AS [Database], [is_db_chaining_on]
FROM [sys].databases
ORDER BY [name];


对于那些开启了跨数据库所有权链的数据库而言,所有权链允许跨越数据库。决定所有权链的方法类似于同一个数据库内的所有权链。只不过每个对象的所有者最后是映射到登陆的,这是有可能的(对于要形成跨数据库所有权链而言,这是必须的)。




在SQL Server 2005及以后的版本里,可以创建一个用户而不用映射到登陆。要查看这些映射,下面的查询显示了存储过程和用户表在登陆一级的最终所有者:



SELECT 
   
so.[name] AS [Object] 
 
, sch.[name] AS [Schema] 
 
, USER_NAME(COALESCE(so.[principal_id], sch.[principal_id])) AS [OwnerUserName]
 
, sp.NAME AS [OwnerLoginName]
 
, so.type_desc AS [ObjectType] 
FROM sys.objects so 
 
JOIN sys.schemas sch 
   
ON so.[schema_id] = sch.[schema_id] 
 
JOIN [sys].database_principals dp
   
ON dp.[principal_id] = COALESCE(so.[principal_id], sch.[principal_id])
 
LEFT JOIN [master].[sys].[server_principals] sp
   
ON dp.sid = sp.sid
WHERE so.[type] IN ('U', 'P'); 


因此,如果一个数据库里有一个对象引用了另一个数据库里的对象,并且这2个数据库都开启了跨数据库所有权链(或许是在服务器一级配置的),而且两个对象有相同的所有者,那么就形成了跨数据库所有权链。就像一个正常的所有权链一样,在第一个对象上检查权限,而第二个对象上不检查权限。然而这里有一点和正常的所有权链不同。查询第一个对象的登陆也必须访问第二个数据库。当第二个数据库是master、msdb或者tempdb时也可以通过guest用户。但如果登陆没有权限连接到第二个数据库的话,查询会失败。


下面的表现是了不同的选项(假定2个数据库都配置为跨数据库所有权链):


Access to 1st DBAccess to 2nd DBGuest User Enabled on 2nd DB?Cross Database Ownership Forms?
YesNoNoNo
YesNoYesYes
YesYesNoYes
YesYesYesYes


在一个对象引用了不同数据库里的对象时,如果跨数据库所有权链不能形成,那么登陆必须映射到每个数据库里的一个用户上,这个用户在对象上有适当的权限。


为了帮助更好的理解,这里有一个例子。我们将创建2个数据库并且创建一个新的用户,然后给予适当的权限,直到最后成功为止。我们用一个有sysadmin权限的帐号来完成这个例子。


注:下面创建数据库的语句用的是最简单的形式。如果你没有缺省的文件位置配置的话,你就需要添加其他的参数。


USE master
GO
CREATE DATABASE Chain1
GO
CREATE DATABASE Chain2
GO

USE Chain2
GO
CREATE TABLE dbo.ChainTest
(name VARCHAR(20))
GO
INSERT INTO ChainTest
VALUES('MSSQLTips')
GO

USE Chain1
GO
CREATE PROC spChainTest
AS
SELECT
* FROM Chain2.dbo.ChainTest
GO

USE master
GO
CREATE LOGIN ChainTest WITH PASSWORD = 'ABC123!!!', DEFAULT_DATABASE = Chain1
GO

USE Chain1
GO
CREATE USER ChainTest
GO
GRANT EXEC ON spChainTest TO ChainTest
GO


现在如果我们用新的登陆“ChainTest”登陆,然后执行存储过程spChainTest的话,你会得到一个错误。


Msg 916, Level 14, State 1, Procedure spChainTest, Line 3
The server principal "ChainTest" is not able to access the database "Chain2" under the current security context.


现在使用sysadmin连接来做下面的改动。这将启用guest帐号并且开启数据库链。


USE Chain2
GO
GRANT CONNECT TO GUEST;
GO
ALTER DATABASE Chain2 SET DB_CHAINING ON
GO


现在如果我们用新的登陆“ChainTest”登陆,然后执行存储过程spChainTest的话,你会得到一个错误。我们有数据库的权限了,但是对象的权限还没有:


Msg 229, Level 14, State 5, Procedure spChainTest, Line 3
The SELECT permission was denied on the object 'ChainTest', database 'Chain2', schema 'dbo'.


所以最后一步是给guest帐号的select权限,通过使用sysadmin连接的用户来运行下面的命令。注意:在系统数据库里guest通过public角色来拥有权限。

.

GRANT SELECT ON dbo.ChainTest TO guest
GO


现在如果我们用新的登陆“ChainTest”登陆,然后执行存储过程spChainTest的话,你会得到下面的结果,它返回我们插入表里的一行。


MSSQLTips



上一篇相关文章
最后编辑拓狼 最后编辑于 2009-07-02 17:57:13
虽有智慧,不如乘势;虽有鎡基,不如待时。
君子学以聚之,问以辨之,宽以居之,仁以行之。
独学而无友,则孤陋而寡闻。
 

回复:理解SQLServer里的跨数据库所有权链

学习!!!
 
1  /  1  页   1 跳转

版权所有 微软BI开拓者 

Powered by Discuz!NT 2.1.202    Copyright © 2001-2010 Comsenz Inc.
Processed in 0.0468756 second(s) , 3 queries.
返顶部