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 中用户没有任何访问权限的内容,因此出现错误。
以下步骤设置模块唱歌。它执行以下操作:
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/