我已将两个SQL Server 2005 dbs(DB1和DB2)还原到运行SQL Server 2008 R2的新框。
所有对象均归dbo所有
我有一个存储过程DB1.dbo.mp_SPTest
。我已将执行权限授予SQLUser1
。
CREATE PROCEDURE mp_SPTest
AS
SELECT DB2.dbo.mf_UserHasAccess("BasicUser", "bob")
mp_SPTest
调用DB2 DB2.dbo.mf_UserHasAccess()
中的标量函数,此函数检查传递的用户名是否是SQL角色的成员.....
CREATE FUNCTION [dbo].[mf_UserHasAccess] (@RoleName varchar(50), @UserName varchar(128))
RETURNS bit
AS
BEGIN
DECLARE @Result bit
SELECT @Result = 1
WHERE @RoleName IN (
SELECT CASE
WHEN (usg.uid is null) THEN 'public'
ELSE usg.name
END AS RoleName
FROM dbo.sysusers usu
LEFT OUTER JOIN (dbo.sysmembers mem
INNER JOIN dbo.sysusers usg
ON mem.groupuid = usg.uid)
ON usu.uid = mem.memberuid
LEFT OUTER JOIN master.dbo.syslogins lo
ON usu.sid = lo.sid
WHERE
(usu.islogin = 1 AND usu.isaliased = 0 AND usu.hasdbaccess = 1)
AND (usg.issqlrole = 1 OR usg.uid is NULL)
AND usu.name = @UserName)
IF @Result <> 1
BEGIN
SET @Result = 0
END
RETURN @Result
END
当我以“SQLUser1”运行此程序时,它告诉我bob不是BasicUser
的成员,但是当我以“sa”运行它时它告诉我他是一名成员。
据我了解...因为dbo拥有过程和函数,那么test2 db中的函数将运行的上下文,因此它应该可以访问相同的用户和登录表。
这在SQL Server 2005上运行良好,无法弄明白。
希望这是有道理的,先谢谢。
答案 0 :(得分:1)
旧的SQL Server 2005很可能启用了cross db ownership chaining选项,而新的SQL Server 2008 R2实例的选项保留了默认值(关闭)。
但是你假设DB1中的'dbo'等于DB2中的'dbo'是错误的。 DB1中的“dbo”是与sys.databases中DB1的owner_sid对应的登录名。同样,DB2中的“dbo”是对应于DB2的sys.databases中的onwer_sid的登录。如果两个登录名不同(如果两个数据库的owner_sid不同),则DB1的“dbo”很可能会映射到其他用户,并且所有权链都会被破坏,即使启用了跨数据库也是如此。运行ALTER AUTHORIZATION ON DATABASE::[DB..] TO [sa]
可以解决这个问题(即它会强制owner_sid匹配)。
最后,你所做的事情从根本上是有缺陷的,因为它依赖于激活跨数据库的所有权链接,这是一个巨大的安全漏洞,请参阅Potential Threats。多better avenue is to use code signing。
答案 1 :(得分:0)
我通过使模式视图或过程在其需要访问的数据库中的模式的所有者下运行来解决这个相同的问题。
USE [TargetDB]
对SCHEMA进行ALTER授权:: [TargetSchema]至[SourceSchema]
例如 使用[DB1]
对SCHEMA进行更改授权:: [mem]至[dbo] GO
允许视图以DB2.DBO.view运行,假设链接已打开,以访问DB1.mem.table中的表。基本上跨数据库链接使它访问目标数据库AS视图所在的模式,而不是拥有数据库的用户。