SQL Server:在视图中而不是在其表中授予对用户的选择访问权限


11

我有一个带有几个数据库的SQL Server 2012实例。在其中一个视图中,我创建了一个视图,该视图在多个数据库中选择表。

我希望用户能够选择该视图,但是它不能选择其表。正是由于用户无法选择表而创建了视图。

我已阅读/programming/368414/grant-select-on-a-view-not-base-tablehttp://msdn.microsoft.com/zh-cn/library/ms188676。 aspx仍然无法正常工作。

如果我GRANT SELECT TABLE TO USER对所有表都执行操作,则用户可以选择视图。但是,如果我撤消到任何表,它将失败。

这应该是一个简单的过程,但是我很难使它起作用。我曾经见过它发生过(实例的所有者为我提供了访问视图的权限,但未在其表中进行操作),但我无法做到这一点或找不到某个知道怎么做的人。

有人可以给我提供有关如何做的教程或代码示例吗?


当用户SELECTs查看我的消息时:

对对象<TABLE>,数据库<DB>,模式的SELECT权限被拒绝dbo

如果我将select授予该表,则错误消息会将表名更改为该视图读取的另一个表。


评论不作进一步讨论;此对话已转移至聊天
保罗·怀特9

Answers:


21

如果希望用户从视图中进行选择,为什么要授予该表?“撤销”是指明确撤销/拒绝吗?拒绝将覆盖授予,因此存在您的问题...您应该能够通过向视图添加授予而不对表进行任何操作来实现此目的

这是一个简单的示例,其中SELECT未在表上显式授予它,而是在视图上。用户可以从视图中选择,但不能从表中选择。

CREATE USER foo WITHOUT LOGIN;
GO
CREATE TABLE dbo.a(id INT);
CREATE TABLE dbo.b(id INT);
GO
CREATE VIEW dbo.v 
AS 
  SELECT a.id FROM a INNER JOIN b ON a.id = b.id;
GO
GRANT SELECT ON dbo.v TO foo;
GO
EXECUTE AS USER = N'foo';
GO
-- works:
SELECT id FROM dbo.v;
GO
-- Msg 229, SELECT denied:
SELECT id FROM dbo.a;
GO
REVERT;

请注意,这假定foo未通过对架构或数据库的显式权限或角色或组成员身份授予提升的特权。

由于您正在多个数据库中使用表(很抱歉,我最初错过了第一句话的结尾),因此您可能还需要在视图不存在的数据库中的表上进行显式授予。为了避免授予对表的选择权,您可以在每个数据库中创建一个视图,然后将这些视图联接起来。

创建两个数据库和一个登录名:

CREATE DATABASE d1;
GO
CREATE DATABASE d2;
GO
USE [master];
GO
CREATE LOGIN blat WITH PASSWORD = 'x', CHECK_POLICY = OFF;
GO

在database中d1,创建一个用户,然后创建一个表和一个针对该表的简单视图。将选择授予用户视图:

USE d1;
GO
CREATE USER blat FROM LOGIN blat;
GO
CREATE TABLE dbo.t1(id INT);
GO
CREATE VIEW dbo.v1
AS
  SELECT id FROM dbo.t1;
GO
GRANT SELECT ON dbo.v1 TO blat;
GO

现在,在第二个数据库中,创建用户,然后创建另一个表和一个视图,该视图将该表连接到中的视图d1。仅将选择授予视图。

USE d2;
GO
CREATE USER blat FROM LOGIN blat;
GO
CREATE TABLE dbo.t2(id INT);
GO
CREATE VIEW dbo.v2
AS
  SELECT v1.id FROM dbo.t2 
    INNER JOIN d1.dbo.v1 AS v1
    ON t2.id = v1.id;
GO
GRANT SELECT ON dbo.v2 TO blat;
GO

现在启动一个新的查询窗口,并将凭据更改为登录名blatEXECUTE AS此处不起作用)。然后从任一数据库的上下文中运行以下命令,它应该可以正常工作:

SELECT id FROM d1.dbo.v2;

这些都应产生Msg 229错误:

SELECT id FROM d1.dbo.t1;
GO
SELECT id FROM d2.dbo.t2;

结果:

消息229,级别14,状态5,第1行
,对对象't1',数据库'd1',模式'dbo'的SELECT权限被拒绝。
消息229,级别14,状态5,第3行
,对对象't2',数据库'd2',模式'dbo'的SELECT权限被拒绝。


1

社区Wiki答案最初由其作者添加到该问题:

这是我所做的:

  1. 在数据库A中创建一个视图,将其中的所有表联接在一起。
  2. 授予SELECT该用户对该视图的访问权限,但不授予其任何表的访问权限。用户成功查询了视图而不是表。
  3. 在数据库B中创建一个视图,将该数据库中的表与数据库A中的视图连接在一起。
  4. SELECT在第二个视图上授予用户访问权限,但也没有任何表的访问权限。用户可以成功查询此最终视图并查看数据。

我认为,视图能够查询其数据库中的表是用户没有直接访问权限,但无法从其他数据库中的表中进行查询,这很奇怪。至少它起作用了。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.