【问题标题】:"service broker" The server principal "sa" is not able to access the database under the current security context“服务代理”服务器主体“sa”无法在当前安全上下文下访问数据库
【发布时间】:2014-04-11 09:13:30
【问题描述】:

我正在使用 SQL Server 2012 Express。

我正在使用 Service Broker 异步运行存储过程。

激活过程必须访问另一个数据库才能执行另一个存储过程。这是代码:

CREATE PROCEDURE [dbo].[GetNewCodes]
    @gintNewCodes bigint,   
    @presNewCodes tinyint,
    @levelNewCodes bigint,
    @quantityNewCodes smallint
AS

    -- Get new codes from INCIC database.
    DECLARE @return_value int,
            @xmlGenerated xml,
            @xmlString NVARCHAR(MAX)

    SET NOCOUNT ON;

        -- Set that this stored procedure is running
        update dbo.RunningSPs with (serializable) set conf_value = 1
        where sp_name = N'GetNewCodes'

        if @@rowcount = 0
        begin
            insert dbo.RunningSPs(sp_name, conf_value) values (N'GetNewCodes', 1)
        end

    EXEC    @return_value = [INCIC].[dbo].[ReadCodeBuffer]
            @gint = @gintNewCodes,
            @pres = @presNewCodes,
            @level = @levelNewCodes,
            @quantity = @quantityNewCodes,
            @xmlGenerated = @xmlGenerated OUTPUT

    SET @xmlString = cast(@xmlGenerated as nvarchar(max))

    -- Process these new codes on TRZ.
    EXEC dbo.ProcessCodes @XmlString = @xmlString

    -- Update that we are not running this procedure any more.
    update dbo.RunningSPs with (serializable) set conf_value = 0
    where sp_name = N'GetNewCodes'

    if @@rowcount = 0
    begin
        insert dbo.RunningSPs(sp_name, conf_value) values (N'GetNewCodes', 0)
    end

问题出在这里:[INCIC].[dbo].[ReadCodeBuffer],错误信息是:

错误:50000
过程 GetNewCodes 中出现不可恢复的错误:916:服务器主体“sa”无法在当前安全上下文下访问数据库“INCIC”。

我已经按照tutorial 实现了服务、队列和激活存储过程。

我该如何解决这个问题?

【问题讨论】:

    标签: sql-server tsql stored-procedures service-broker sql-server-2012-express


    【解决方案1】:

    阅读Call a procedure in another database from an activated procedure

    问题是激活的过程在 EXECUTE AS USER 上下文中运行,因此受到数据库模拟限制(它们在数据库中被沙盒化)。全部在Extending Database Impersonation by Using EXECUTE AS中解释。

    解决方案是对激活的过程进行签名,并在目标数据库中创建从签名证书派生的用户,并授予该派生用户所需的权限。第一个链接显示了一个完整的示例。

    【讨论】:

      【解决方案2】:

      Remus Rusanu 的回答显然是明确而正确的。 (任何与 Broker Services 打交道的人都知道他的专业知识和宝贵的博客。)

      我只是想记录一下我的经验,因为在搜索“服务器主体“sa”无法访问数据库...”时,谷歌会直接回答这个问题。

      在我的例子中,我是从一个激活的过程中调用另一个数据库,但直接调用一个 sql 语句,而不是一个存储过程。

      最初,跨数据库调用在没有签名证书和使用模拟的情况下运行良好。然后,在进行小的语法更改后,它开始返回上述错误消息。

      以下是不需要签名证书的工作:

      IF  EXISTS (SELECT name FROM sys.databases WHERE name = N'MyOtherDb')
      

      这就是引发安全异常的原因:

      IF DB_ID(N'MyOtherDb') IS NOT NULL
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-10-07
        • 1970-01-01
        • 2013-10-01
        • 2018-03-29
        相关资源
        最近更新 更多