SQL Server 2019 - 服务器主体“sa”无法在当前安全上下文下访问数据库“DB_NAME”

问题描述 投票:0回答:4

我编写了以下存储过程:

CREATE PROCEDURE dbo.usp_DEMO 
    @LOGINSQL VARCHAR(30), 
    @DBNAME VARCHAR(40) 
WITH EXECUTE AS owner
AS 
    DECLARE @SQL NVARCHAR(1000) 
    SET @SQL = 'USE' 
    SET @SQL = @SQL + ' ' + @DBNAME + ' ' + ' CREATE USER ' + ' ' 
               + @LOGINSQL + ' ' + ' FOR LOGIN ' + ' ' + @LOGINSQL + ' ' 
               + ' ALTER ROLE [DB_OWNER] ADD MEMBER ' + ' ' 
               + @LOGINSQL 
    EXEC sp_executesql @SQL

这样跑步:

use master
go
exec usp_DEMO '<LOGIN>','<DATABASE>'

我在 SQL Server 2019 STD Edition (RTM-CU6) (KB4563110) 中从

Master
运行,并收到此错误:

消息 916,第 14 级,状态 2,第 14 行
服务器主体“”无法在当前安全上下文下访问数据库“”。

这个想法是使用存储过程将登录映射到数据库并赋予

db_owner
角色。

知道如何解决该错误吗?

sql-server sql-server-2019 database-security
4个回答
6
投票

检查目标数据库所有者,如果数据库所有者不是

sa
或目标数据库的
TRUSTWORTHY
属性为 OFF,您将收到“服务器主体“sa”无法访问数据库”在存储过程中使用
EXECUTE AS
模拟 SA 时出现“DB_NAME”在当前安全上下文下的错误:

https://learn.microsoft.com/en-us/previous-versions/sql/sql-server-2008-r2/ms188304(v=sql.105)?redirectedfrom=MSDN:

当使用 EXECUTE AS USER 语句模拟主体时,或在数据库范围的模块中使用 EXECUTE AS 子句模拟主体时,默认情况下模拟范围仅限于数据库。这意味着引用数据库范围之外的对象将返回错误。

选项解决了错误“服务器主体“sa”无法访问当前安全上下文下的数据库“DB_NAME””

注意:在下面的选项中将 {{TargetDb}} 替换为实际的 DB_NAME

  1. 将目标数据库所有者更改为
    sa
USE {{TargetDb}} 
sp_changedbowner 'sa'
  1. 或者打开目标数据库中的
    TRUSTWORTHY
    属性:
ALTER DATABASE {{TargetDb}} SET TRUSTWORTHY ON

1
投票

删除

WITH EXECUTE AS owner


1
投票

我刚刚解决了与您非常相似的情况。在我的场景中,我希望具有最低安全权限的用户能够恢复数据库并向其中添加一些具有角色的 SQL 用户。 EXECUTE AS 的存储过程可用于恢复数据库,但无法使其用于创建这些用户。可能是因为问题的动态 SQL + 跨数据库性质。

最终我在存储过程签名的帮助下解决了这个问题

CREATE CERTIFICATE ElevationCertificate
ENCRYPTION BY PASSWORD = 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'  
WITH SUBJECT = 'For privileges elevation',   
EXPIRY_DATE = '1/10/2025';  
GO

ADD SIGNATURE TO MyStoredProcedure   
BY CERTIFICATE ElevationCertificate  
WITH PASSWORD = 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx';  
GO


CREATE LOGIN ElevatedUser
    FROM CERTIFICATE ElevationCertificate;
GO
   
EXEC master..sp_addsrvrolemember @loginame = N'ElevatedUser', @rolename = N'sysadmin'

0
投票

我找到了“Msg 916,Level 14,State 2,Line 63”的另一个答案

我的数据库未使用 TrustWorthy,所有者是我们的“sa”帐户。

但是我用于访问的 AD 组现在是安全性的 Global Distribution 组。

我的用户遇到了同样的错误,一旦我创建了一个新的 AD 安全组,团队就进入了。

引用回复

不,这行不通。

为了使 AD 中的权限正确传播,安全组的成员必须是安全主体。 这意味着每个对象都需要一个活动 SID,然后可以使用该活动 SID 将权限从一个成员链接到下一个成员。 由于通讯组有一个不活动的 SID,因此它会破坏链。

© www.soinside.com 2019 - 2024. All rights reserved.