web-dev-qa-db-ja.com

SQL Server:テーブルではなくビューでユーザーに選択アクセスを許可する

いくつかのデータベースを含むSQL Server 2012インスタンスがあります。それらの1つで、データベース以外のテーブルを選択するビューを作成しました。

ユーザーがそのビューを選択できるようにしたいのですが、そのテーブルを選択してはなりません。ユーザーがテーブルを選択できないため、ビューが作成されました。

私は https://stackoverflow.com/questions/368414/grant-select-on-a-view-not-base-tablehttp://msdn.Microsoft .com/en-us/library/ms188676.aspx で、まだ機能していません。

すべてのテーブルに対してGRANT SELECT TABLE TO USERを実行すると、ユーザーはビューを選択できます。しかし、いずれかのテーブルを取り消すと、失敗します。

これは簡単な手順ですが、機能させるのに苦労しています。以前にそれが発生するのを見たことがありますが(インスタンスの所有者がビューへのアクセスを許可し、テーブルへのアクセスを許可していません)、それを実行したり、方法を知っている人を見つけることができません。

誰かがそれを行う方法についてのチュートリアル、またはコード例を私に提供できますか?


ユーザーSELECTsビューにメッセージが表示されると:

オブジェクト<TABLE>、データベース<DB>、スキーマdboに対するSELECT権限が拒否されました。

そのテーブルに選択を許可すると、エラーメッセージにより、テーブル名がビューが読み取る別のテーブルに変更されます。

11
Hikari

ユーザーがビューから選択できるようにする場合、なぜテーブルに付与するのですか? 「取り消す」とは、明示的に取り消す/拒否することを意味しますか? Denyはgrantをオーバーライドするので、問題があります... grant ビューにを追加して、テーブルに対して何もしないことでこれを実現できるはずです。

以下は、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に、スキーマまたはデータベースに対する明示的な権限、またはロールまたはグループメンバーシップによる昇格された権限が付与されていないことを前提としています。

複数のデータベースでテーブルを使用しているため(最初に最初の文の終わりを逃してしまい申し訳ありません)、ビューが存在しないデータベース内のテーブルに対する明示的な付与も必要になる場合があります。テーブルへの選択の許可を回避するために、各データベースでビューを作成してから、ビューを結合することができます。

2つのデータベースと1つのログインを作成します。

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

データベース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

次に、2番目のデータベースでユーザーを作成してから、別のテーブルと、そのテーブルを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権限が拒否されました。

21
Aaron Bertrand

コミュニティwikiの回答 作成者が最初に質問に追加したもの:

これは私がやったことです:

  1. DB Aにビューを作成し、その中のすべてのテーブルを結合しました。
  2. そのビューのユーザーにSELECTアクセス権を付与しました。そのテーブルへのアクセス権は付与していません。ユーザーは、テーブルではなくビューを正常にクエリできました。
  3. DB Bにビューを作成し、このDBのテーブルをDB Aのビューと結合しました。
  4. この2番目のビューのユーザーにSELECTアクセス権を付与しました。また、どのテーブルにも付与していません。ユーザーはこの最終ビューを正常にクエリしてデータを表示することができました。

ビューがそのDBのテーブルをクエリできるのは奇妙だと思います。ユーザーが直接アクセスすることはできませんが、他のDBからのテーブルでは実行できません。少なくともそれはうまくいった。

1
user126897

サーバーでCross database ownership chainingをアクティブにすると、クロスデータベースビューが正常に機能します。

https://docs.Microsoft.com/en-us/dotnet/framework/data/adonet/sql/enabling-cross-database-access-in-sql-server

リスクを気にする

0
user2461271