単一のビューへのアクセス権を持つユーザーを追加するにはどうすればよいですか?


14

MSSQL Server Management Studio 2008を使用していますが、データ調整のためにビューをサードパーティに公開する必要があります。適切なビューを作成しましたが、ユーザーを作成して、そのユーザーにビューから選択するための適切なアクセス許可を与えることができません。

ウィザードに従ってログインとユーザーを作成し、[選択可能]チェックボックスをオンにして[セキュリティ保護可能]セクションにビューを追加しました。すべてが順調に見えましたが、そのユーザーとしてログインして「Select * from MyViewName」を実行しようとすると、選択権限が拒否されたことがわかりました。

私はユーザーを再作成し(今回はウィザードの代わりにSQLを使用するだけです)、選択権限を明示的に付与しましたが、今ではエラーが発生しています:( Msg 916, Level 14, State 1, Line 2 The server principal "username" is not able to access the database "unrelated_db" under the current security context.無関係なデータベースにアクセスしようとする理由がわかりません...)

ここからどこに行くべきか本当にわかりません。繰り返しますが、基本的に必要なのは、サードパーティにデータベースに接続してこのビューから選択させるために、サードパーティに提供できるユーザーを作成することです。


3
ビューは他のデータベースのベーステーブルを参照しますか?その場合、所有権の連鎖に対処する必要があります。また、現在、データベースコンテキストが目的のデータベースに設定されていることを確認してください。
トーマスストリンガー

ビューの依存関係を確認する方法はありますか?私が知っている限りでは、ビューのすべてがメインデータベース内に含まれている必要があります。ビューは3つのフィールドで、2つは支払い詳細テーブルから、もう1つはアカウント詳細テーブルへの結合からのものですが、両方のテーブルは同じデータベース(およびビューと同じデータベース)にあります。
ベロジャソン

回答:


16

これにはUIを使用しないでください。紛らわしい混乱です。

特定のログインに対して、1つのビューから選択する権限のみを持つユーザーをデータベースに作成したいようです。そのため、すでにログインが作成されているため:

USE your_db;
GO
CREATE USER username FROM LOGIN username;
GO
GRANT SELECT ON dbo.MyViewName TO username;
GO

ここでの編集は、言及したエラーを引き起こすスクリプトの例です。

まず、unrelated_dbにテーブルを作成します。

CREATE DATABASE unrelated_db;
GO
USE unrelated_db;
GO
CREATE TABLE dbo.foo(bar INT);
GO

次に、比較的制限されたログインを作成します。

USE [master];
GO
CREATE LOGIN username WITH PASSWORD='foo', CHECK_POLICY = OFF;
GO

次に、ビューが存在するデータベースを作成し、ユーザーとしてログインを追加します。

CREATE DATABASE velojason;
GO
USE velojason;
GO
CREATE USER username FROM LOGIN username;
GO

次に、他のデータベースのテーブルを参照する関数と、他のテーブルの同義語を作成します。

CREATE FUNCTION dbo.checkbar()
RETURNS INT
AS 
BEGIN
    RETURN 
    (
      SELECT TOP (1) bar 
        FROM unrelated_db.dbo.foo 
        ORDER BY bar
    );
END
GO
CREATE SYNONYM dbo.foo FOR unrelated_db.dbo.foo;
GO

次に、ローカルテーブルを作成します。

CREATE TABLE dbo.PaymentDetails
(
  PaymentID INT
);
GO

次に、テーブル、関数、シノニムを参照するビューを作成し、付与SELECTusernameます:

CREATE VIEW dbo.SomeView
AS
  SELECT 
    p.PaymentID, 
    x = dbo.checkbar(), -- function that pulls from other DB
    y = (SELECT bar FROM dbo.foo) -- synonym to other DB
    FROM dbo.PaymentDetails AS p;
GO
GRANT SELECT ON dbo.SomeView TO username;
GO

次に、asを実行してusername、ビューからローカル列のみを選択してみます。

EXECUTE AS USER = 'username';
GO
  -- even though I don't reference any of the columns 
  -- in the other DB, I am denied SELECT on the view:
SELECT PaymentID FROM dbo.SomeView;
GO
REVERT;
GO

結果:

メッセージ916、レベル14、状態1、行3
サーバープリンシパル "username"は、現在のセキュリティコンテキストでデータベース "unrelated_db"にアクセスできません。

次に、外部オブジェクトを参照しないようにビューを変更し、上記をSELECT再度実行すると動作します:

ALTER VIEW dbo.SomeView
AS
  SELECT 
    p.PaymentID 
    --x = dbo.checkbar(),
    --y = (SELECT bar FROM dbo.foo)
    FROM dbo.PaymentDetails AS p;
GO

Payment Details、Account Details、およびMyViewオブジェクトのスクリプトを表示する以外に、このクエリが結果を返すかどうかをお知らせください。カタログビューsys.sql_expression_dependenciesでさまざまなオブジェクトへの参照を見つけることができますが、このビューは完全ではありません-更新されているすべてのビューに依存していると思います(たとえば、ビューが他のビューを参照する場合、または基になるスキーマが変更された場合)正確に。

DECLARE 
  @dbname   SYSNAME = N'unrelated_db',
  @viewname SYSNAME = N'dbo.SomeView';

SELECT DISTINCT 
    [This object] = 
    OBJECT_SCHEMA_NAME([referencing_id]) 
      + '.' + OBJECT_NAME([referencing_id]), 
    [references this object] = 
    OBJECT_SCHEMA_NAME([referenced_id]) 
      + '.' + OBJECT_NAME([referenced_id]), 
    [and touches this database] = referenced_database_name,
    [and is a(n)] = o.type_desc,
    [if synonym, it references] = s.base_object_name
FROM sys.sql_expression_dependencies AS d
LEFT OUTER JOIN sys.objects AS o
ON o.[object_id] = d.referenced_id
LEFT OUTER JOIN sys.synonyms AS s
ON d.referenced_id = s.[object_id]
AND s.base_object_name LIKE '%[' + @dbname + ']%'
WHERE OBJECT_ID(@viewname) IN (
        referenced_id, 
        referencing_id, 
        (SELECT referencing_id FROM sys.sql_expression_dependencies 
        WHERE referenced_database_name = @dbname)
) OR referenced_database_name = @dbname;

SQL Serverは、単にunrelated_db面白さのためにアクセスしようとするだけではありません...使用しようとしているビューからそのデータベースに何らかの結び付けがなければなりません。残念ながら、ビューの定義と、それが触れるオブジェクトの詳細が表示されない場合は、推測するだけです。私が考えることができる2つの主なものは、3部構成の名前を使用する同義語または関数ですが、実際のスクリプトを見ると、推測するよりもはるかに良いアイデアが得られます。:-)

をチェックすることもできますがsys.dm_sql_referenced_entities、この関数は上記の例では有用なものを何も返しません。


6
create login YourTpvLogin with password = 'enter new password here'
go

use SomeDb
go

create user YourTpvUser for login YourTpvLogin
go

grant select on YourView to YourTpvUser
go

これをテストするには、次を実行します。

execute as user = 'YourTpvUser'
go

select *
from YourView

revert
go

どうやらこれは再帰的に特権を付与しません。ユーザーは「YourView」から選択できますが、「YourView」が他のリレーション/データベースに依存している場合、失敗します。サーバープリンシパル「YourTpvUser」は、現在のセキュリティコンテキストでデータベース「OtherDb」にアクセスできません。
lilalinux
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.