1

我正在使用SQL Server 2012 Express。「服務代理」服務器主體「sa」無法在當前安全環境下訪問數據庫

我正在使用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],並且錯誤信息是:

Error: 50000
Unrecoverable error in procedure GetNewCodes: 916: The server principal "sa" is not able to access the database "INCIC" under the current security context.

我跟了這tutorial實施服務,隊列和激活存儲過程。

我該如何解決這個問題?

回答

5

閱讀Call a procedure in another database from an activated procedure

問題是激活的過程在EXECUTE AS USER環境下運行,因此受到數據庫模擬限制(它們在數據庫中被沙箱化)。全部在Extending Database Impersonation by Using EXECUTE AS中解釋。

解決方案是簽署激活的過程並創建從目標數據庫中的簽名證書派生的用戶,並授予此派生用戶所需的權限。第一個鏈接顯示了一個完整的例子。

0

Remus Rusanu的回答顯然是確定無誤的。 (任何與經紀服務有關的人都知道他的專業知識和寶貴的博客。)

我只是想記錄我的經驗,因爲谷歌將直接搜索這個問題「服務器主體」sa「無法訪問數據庫...

在我的情況下,我從一個激活的過程中調用另一個數據庫,但直接調用一個sql語句,而不是存儲過程。

最初,跨數據庫調用工作正常,沒有簽名證書和使用模擬。然後,在語法小改動後,它開始返回上述錯誤信息。

這裏是無需什麼工作了簽名的證書:

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

,這裏是什麼激起了安全例外:

IF DB_ID(N'MyOtherDb') IS NOT NULL 
相關問題