访问基于另一个数据库中的表的视图,而无需在该另一个数据库中的帐户

tom*_*tom 12 sql-server-2008 security sql-server permissions view

我根据 database2 中的表在 database1 中创建了视图。我SELECT授予了一个只能访问 database1 的用户的权限。用户无法使用此视图,因为他在 database2 中没有帐户。我该如何解决这个问题?我不想在 database2 中创建帐户。

Sol*_*zky 10

这很容易使用模块签名以非常安全的方式完成。这将类似于我的以下两个答案,也在 DBA.StackExchange 上,给出了这样做的例子:

具有执行方式、跨数据库查询和模块签名的存储过程安全性

使用跨数据库证书时触发器中的权限

这个特定问题的不同之处在于它处理一个视图,并且视图不能被签名。因此,您需要将视图更改为多语句表值函数 (TVF),因为它们可以签名并且可以像视图一样访问(好吧,用于SELECT访问)。

以下示例代码显示了执行问题中所要求的操作,因为登录/用户“RestrictedUser”只能访问“DatabaseA”并且还能够从“DatabaseB”获取数据。这只能通过从这个 TVF 中进行选择才能起作用,并且仅由于它已被签名。

在仍然使用视图的同时完成这种类型的跨数据库访问,并且给用户任何额外的权限,需要启用跨数据库所有权链接。这远不那么安全,因为它对两个数据库之间的所有对象都是完全开放的(它不能仅限于某些对象和/或用户)。模块签名只允许这一个 TVF 具有跨 DB 访问权限(用户没有权限,TVF 有权限),而不SELECT能从 TVF访问的用户根本无法访问“DatabaseB”。

USE [master];

CREATE LOGIN [RestrictedUser] WITH PASSWORD = 'No way? Yes way!';
GO

---

USE [DatabaseA];

CREATE USER [RestrictedUser] FOR LOGIN [RestrictedUser];

GO
CREATE FUNCTION dbo.DataFromOtherDB()
RETURNS @Results TABLE ([SomeValue] INT)
AS
BEGIN
    INSERT INTO @Results ([SomeValue])
        SELECT [SomeValue]
        FROM   DatabaseB.dbo.LotsOfValues;

    RETURN;
END;
GO

GRANT SELECT ON dbo.[DataFromOtherDB] TO [RestrictedUser];
GO
---

USE [DatabaseB];

CREATE TABLE dbo.[LotsOfValues]
(
    [LotsOfValuesID] INT IDENTITY(1, 1) NOT NULL
        CONSTRAINT [PK_LotsOfValues] PRIMARY KEY,
    [SomeValue] INT
);

INSERT INTO dbo.[LotsOfValues] VALUES
    (1), (10), (100), (1000);
GO

---

USE [DatabaseA];

SELECT * FROM dbo.[DataFromOtherDB]();


EXECUTE AS LOGIN = 'RestrictedUser';

SELECT * FROM dbo.[DataFromOtherDB]();
/*
Msg 916, Level 14, State 1, Line XXXXX
The server principal "RestrictedUser" is not able to access
the database "DatabaseB" under the current security context.
*/

REVERT;
Run Code Online (Sandbox Code Playgroud)

上述所有步骤都重新创建了当前情况:用户有权访问 DatabaseA,有权与 DatabaseA 中的对象交互,但由于 DatabaseA 中的该对象访问了 DatabaseB 中用户没有任何访问权限的内容,因此出现错误。

以下步骤设置模块唱歌。它执行以下操作:

  1. 在 DatabaseA 中创建证书
  2. 用证书签署 TVF
  3. 将证书(不带私钥)复制到数据库 B
  4. 从证书在 DatabaseB 中创建用户
  5. 授予SELECT权限表中DatabaseB的基于证书的用户

模块签名设置:

CREATE CERTIFICATE [AccessOtherDB]
    ENCRYPTION BY PASSWORD = 'SomePassword'
    WITH SUBJECT = 'Used for accessing other DB',
    EXPIRY_DATE = '2099-12-31';

ADD SIGNATURE
    TO dbo.[DataFromOtherDB]
    BY CERTIFICATE [AccessOtherDB]
    WITH PASSWORD = 'SomePassword';

---
DECLARE @CertificatePublicKey NVARCHAR(MAX) =
            CONVERT(NVARCHAR(MAX), CERTENCODED(CERT_ID(N'AccessOtherDB')), 1);

SELECT @CertificatePublicKey AS [Cert / PublicKey]; -- debug

EXEC (N'USE [DatabaseB];
CREATE CERTIFICATE [AccessOtherDB] FROM BINARY = ' + @CertificatePublicKey + N';');
---


EXEC (N'
USE [DatabaseB];
CREATE USER [AccessOtherDbUser] FROM CERTIFICATE [AccessOtherDB];

GRANT SELECT ON dbo.[LotsOfValues] TO [AccessOtherDbUser];
');

---



EXECUTE AS LOGIN = 'RestrictedUser';

SELECT * FROM dbo.[DataFromOtherDB]();
-- Success!!

SELECT * FROM [DatabaseB].[dbo].[LotsOfValues];
/*
Msg 916, Level 14, State 1, Line XXXXX
The server principal "RestrictedUser" is not able to access
the database "DatabaseB" under the current security context.
*/

REVERT;
Run Code Online (Sandbox Code Playgroud)

如果访问需要通过视图,无论出于何种原因,您都可以简单地创建一个从上面显示的 TVF 中选择的视图。而且,在这种情况下,SELECT不访问没有需要被授予TVF,只能查看,这表现如下:

GO
CREATE VIEW dbo.[DataFromTVF]
AS
SELECT [SomeValue]
FROM   dbo.DataFromOtherDB();
GO

-- Remove direct access to the TVF as it is no longer needed:
REVOKE SELECT ON dbo.[DataFromOtherDB] FROM [RestrictedUser];

GRANT SELECT ON dbo.[DataFromTVF] TO [RestrictedUser];
Run Code Online (Sandbox Code Playgroud)

现在来测试一下:

EXECUTE AS LOGIN = 'RestrictedUser';


SELECT * FROM dbo.[DataFromOtherDB]();
/*
Msg 229, Level 14, State 5, Line XXXXX
The SELECT permission was denied on the object 'DataFromOtherDB',
database 'DatabaseA', schema 'dbo'.
*/


SELECT * FROM [OwnershipChaining].[dbo].[LotsOfValues];
/*
Msg 916, Level 14, State 1, Line XXXXX
The server principal "RestrictedUser" is not able to access
the database "DatabaseB" under the current security context.
*/


SELECT * FROM dbo.[DataFromTVF];
-- Success!!


REVERT;
Run Code Online (Sandbox Code Playgroud)

有关模块签名的更多信息,请访问:https : //ModuleSigning.Info/