服务器主体“XYuser”无法访问当前安全上下文下的数据库“Ydb”

时间:2009-02-12 11:31:52

标签: sql sql-server sql-server-2005 ssms

系统规格

Microsoft SQL Server Management Studio          9.00.4035.00  
Microsoft Analysis Services Client Tools        2005.090.4035.00  
Microsoft Data Access Components (MDAC)         2000.085.1132.00  
                                                 (xpsp.080413-0852)  
Microsoft MSXML                                 2.6 3.0 4.0 5.0 6.0 
Microsoft Internet Explorer                     7.0.5730.13  
Microsoft .NET Framework                        2.0.50727.1433  
Operating System                                5.1.2600  

在名为 BHAVMSQL02 的SQL Server 2005上,我有两个数据库 Mattercentre_dev CMSNET_DEV Mattercentre_dev 有一个存储过程,可以从 CMSNET_DEV 中的表构建列表。存储过程看起来 像这样...

USE [Mattercentre_dev]
GO
/****** Object:  StoredProcedure [dbo].[UDSPRBHPRIMBUSTYPE]   
  Script Date:02/12/2009 10:18:10 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER OFF
GO


ALTER PROCEDURE [dbo].[UDSPRBHPRIMBUSTYPE] WITH EXECUTE AS 'Readuser' AS

DECLARE @SERVERNAME nvarchar(30)
DECLARE @DBASE nvarchar(30)
DECLARE @SQL nvarchar(2000)
SET @SERVERNAME = Convert(nvarchar,
  (SELECT spData FROM dbSpecificData WHERE spLookup = 'CMSSERVER'))
SET @DBASE = Convert(nvarchar,
  (SELECT spData FROM dbSpecificData WHERE spLookup = 'CMSDBNAME'))

SET @SQL = 
'SELECT 
    null as Code
    , ''(not specified)'' as Description  
UNION SELECT 
    clnt_cat_code as Code
    , clnt_cat_desc as Description   
FROM '
    + @SERVERNAME + '.' + @DBASE + '.dbo.hbl_clnt_cat  
WHERE 
    inactive = ''N''  
ORDER BY Description'
PRINT @SQL

EXECUTE sp_executeSQL @SQL

@SERVERNAME == 'BHAVMSQL02'

@DBASE      == 'CMSNET_DEV'

执行存储过程时,出现以下错误消息...

The server principal "ReadUser" is not able to access the database "CMSNET_DEV" under the current security context.

在Google上搜索错误消息后,我执行了以下修复...

  • 从中删除了用户ReadUser BHAVMSQL02 - >数据库 - > Mattercentre_dev - >安全 - >用户
  • 从BHAVMSQL02设置ReadUser - > 安全 - >登录以下内容 设置...

    一般
    登录名 - readUser
    密码 - xxxxxxxxxxxx
    确认 - xxxxxxxxxxxx
    默认db - master
    默认lg - 英国英语
    其他一切 - 取消设置

    服务器角色 仅公开集

    用户映射 CMSNET_DEV - ReadUser - dbo
    数据库角色成员资格 - db_owner,public

    Mattercentre_dev - ReadUser - dbo
    数据库角色成员资格 - db_owner,public

然后我运行了以下脚本......

ALTER DATABASE CMSNET_DEV SET TRUSTWORTHY ON
GO
ALTER DATABASE mattercentre_dev SET TRUSTWORTHY ON
GO

我重新运行存储过程并再次执行它,我仍然有相同的 错误信息。

我在Stack Overflow和建议的解决方案中看到了这个问题 与我自己的相似。

1 个答案:

答案 0 :(得分:2)

当存储过程包含动态SQL时,您无法使用所有权链接,即这样做会破坏所有权链。

为了使其正常工作,您需要使用证书对存储过程进行签名。

以下是一篇精彩的文章,其中包含有关签署存储过程的说明。

http://www.sommarskog.se/grantperm.html

更详细地看一下,您使用“执行为子句”的事实应该否定由于合并动态SQL而导致所有权链被破坏的事实。

考虑到这一点,可能的问题是由于某种原因,登录“ReadUser”没有对相关数据库的适当读取访问权限,但是不应该是这种情况,因为登录是一个成员两个数据库中的db_owner角色。也就是说,如果数据库角色已从原始状态改变,那么这可能不成立。

为了测试问题是否与“ReadUser”登录无隔离,我建议创建一个新的SQL Server登录,并将登录映射到两个数据库(通过创建同名的数据库登录),并具有适当的读访问权限。然后修改存储过程以执行新登录。