SQL Server 2008 R2 跨数据库所有权链接不起作用?
我已将两个 SQL Server 2005 数据库(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 上运行良好,但无法弄清楚。
希望这是有道理的,提前致谢。
I have restored two SQL Server 2005 dbs (DB1 & DB2) to a new box running SQL Server 2008 R2.
All objects are owned by dbo
I have a stored procedure DB1.dbo.mp_SPTest
. I have given execute permissions to SQLUser1
.
CREATE PROCEDURE mp_SPTest
AS
SELECT DB2.dbo.mf_UserHasAccess("BasicUser", "bob")
mp_SPTest
calls a scalar function in DB2 DB2.dbo.mf_UserHasAccess()
, this function checks if the username passed is a member of a SQL Role.....
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
When I run this procedure as "SQLUser1" it tells me that bob is not a member of BasicUser
but when I run it as "sa" it tells me that he IS a member.
As I understand it... because both procedure and function are owned by dbo then that is the context that the function in test2 db would run, therefore it should have access to the same user and login tables.
This worked fine on SQL Server 2005, cant figure it out.
Hope this makes sense, thanks in advance.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
旧的 SQL Server 2005 很可能已启用跨数据库所有权链接选项打开,而新的 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 匹配)。
最后,您所做的事情从根本上来说是有缺陷的,因为它依赖于激活跨数据库的所有权链,这是一个巨大的安全漏洞,请参阅潜在威胁。一个更好的途径就是使用代码签名。
Most likely the old SQL Server 2005 had the cross db ownership chaining option turned on, while the new SQL Server 2008 R2 instance has the option left at its default value (off).
But your assumption that 'dbo' in DB1 equate to 'dbo' in DB2 is wrong. 'dbo' in DB1 is the login who corresponds to the owner_sid of DB1 in sys.databases. 'dbo' in DB2 is, likewise, the login that corrsponds to the onwer_sid in sys.databases for DB2. If the two logins are different (if the owner_sid of the two databases is different) then very likely 'dbo' of DB1 will map to some other user and the ownership chain is broken, even if enabled to cross databases. Running
ALTER AUTHORIZATION ON DATABASE::[DB..] TO [sa]
would fix this problem (ie. it would force the owner_sid to match).And finally, what you're doing is fundamentally flawed, as it relies on activating ownership chaining across databases, which is a huge security hole, see Potential Threats. A much better avenue is to use code signing.
我通过使视图或过程的架构在其需要访问的数据库中架构的所有者下运行来解决了这个相同的问题。
使用 [TargetDB]
ALTER AUTHORIZATION ON SCHEMA::[TargetSchema] TO [SourceSchema]
例如
使用 [DB1]
将 SCHEMA::[mem] 上的授权更改为 [dbo]
GO
假设链接已打开,将允许视图作为 DB2.DBO.view 运行,以访问 DB1.mem.table 中的表。本质上,跨数据库链接导致它访问目标数据库作为视图所在的模式,而不是拥有数据库的用户。
I solved this identical problem by making the schema the view or procedure is running under the owner of the schemas in the databases it needs to access.
USE [TargetDB]
ALTER AUTHORIZATION ON SCHEMA::[TargetSchema] TO [SourceSchema]
For example
USE [DB1]
ALTER AUTHORIZATION ON SCHEMA::[mem] TO [dbo]
GO
Would allow a view run as DB2.DBO.view assuming chaining is turned on, to access a table in DB1.mem.table. Essentially cross db chaining causes it to access the target DB AS the schema the view is under, not the user who owns the database.