2

系统规格

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_devCMSNET_DEVMattercentre_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.

谷歌搜索错误消息后,我进行了以下修复...

  • 从 BHAVMSQL02 -> Databases -> Mattercentre_dev -> Security -> Users 中删除了用户 ReadUser
  • 从 BHAVMSQL02 设置 ReadUser -> 安全 -> 使用以下设置登录...

    通用
    登录名 - readUser
    密码 - xxxxxxxxxxxx
    Confirm - xxxxxxxxxxxx
    Default db - master
    default lg - British English
    Everything Else - Unset

    仅限服务器角色的公共集

    用户映射 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 中查找了这个问题,建议的解决方案与我自己的类似。

4

1 回答 1

2

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

为了使其工作,您将需要使用证书来签署您的存储过程。

下面是一篇精彩的文章,其中包含对存储过程进行签名的说明。

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

更详细地查看这一点,您使用“execute as 子句”这一事实应该否定所有权链因合并动态 SQL 而被破坏的事实。

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

To test that the issue is not isolated to the “ReadUser” login I would suggest creating a new SQL Server Login, and mapping the login to both databases (there by creating database logins of the same name) with appropriate read access. Then modify the stored procedure to execute as the new login.

于 2009-02-12T13:22:06.897 回答