SQL Server: Gewähren Sie einem Benutzer in einer Ansicht und nicht in seinen Tabellen Auswahlzugriff

11

Ich habe eine SQL Server 2012-Instanz mit einigen Datenbanken. In einer davon habe ich eine Ansicht erstellt, die Tabellen in mehr als einer Datenbank auswählt.

Ich möchte, dass ein Benutzer diese Ansicht auswählen kann, aber er darf seine Tabellen nicht auswählen. Die Ansicht wurde genau erstellt, weil der Benutzer die Tabellen nicht auswählen kann.

Ich habe /programming/368414/grant-select-on-a-view-not-base-table und http://msdn.microsoft.com/en-us/library/ms188676 gelesen . aspx und trotzdem funktioniert es nicht.

Wenn ich GRANT SELECT TABLE TO USERfür alle Tabellen eine mache , kann der Benutzer die Ansicht auswählen. Aber wenn ich eine Tabelle widerrufe, schlägt dies fehl.

Dies sollte ein einfaches Verfahren sein, aber ich habe Probleme, es zum Laufen zu bringen. Ich habe es schon einmal gesehen (der Besitzer einer Instanz hat mir Zugriff auf eine Ansicht gewährt und es nicht mit ihren Tabellen gemacht), aber ich kann es nicht tun oder jemanden finden, der weiß wie.

Könnte mir jemand ein Tutorial dazu oder ein Codebeispiel geben?


Wenn der Benutzer SELECTsdie Ansicht erhält, erhalte ich die Nachricht:

Die SELECT-Berechtigung wurde für das Objekt <TABLE>, die Datenbank <DB>und das Schema verweigert dbo.

Wenn ich dieser Tabelle eine Auswahl erteile, ändert die Fehlermeldung den Tabellennamen in eine andere Tabelle, die in der Ansicht gelesen wird.

Hikari
quelle
Kommentare sind nicht für eine ausführliche Diskussion gedacht. Dieses Gespräch wurde in den Chat verschoben .
Paul White 9

Antworten:

21

Wenn Sie möchten, dass Benutzer aus der Ansicht auswählen, warum gewähren Sie der Tabelle? Mit "widerrufen" meinen Sie explizit widerrufen / verweigern? Verweigern überschreibt die Gewährung, sodass Ihr Problem vorliegt. Sie sollten dies erreichen können, indem Sie der Ansicht eine Bewilligung hinzufügen und in den Tabellen nichts tun.

Hier ist ein kurzes Beispiel, in dem SELECTnicht explizit für die Tabelle, sondern für die Ansicht gewährt wurde. Der Benutzer kann aus der Ansicht auswählen, jedoch nicht aus der Tabelle.

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;

Beachten Sie, dass davon ausgegangen foowird, dass keine erhöhten Berechtigungen durch explizite Berechtigungen für das Schema oder die Datenbank oder durch Rollen- oder Gruppenmitgliedschaft gewährt wurden.

Da Sie Tabellen in mehreren Datenbanken verwenden (es tut mir leid, dass ich das Ende dieses ersten Satzes anfangs verpasst habe), benötigen Sie möglicherweise auch explizite Berechtigungen für die Tabelle (n) in der Datenbank, in der die Ansicht nicht vorhanden ist. Um zu vermeiden, dass den Tabellen eine Auswahl zugewiesen wird, können Sie in jeder Datenbank eine Ansicht erstellen und dann die Ansichten verbinden.

Erstellen Sie zwei Datenbanken und ein Login:

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

d1Erstellen Sie in der Datenbank einen Benutzer und erstellen Sie dann eine Tabelle und eine einfache Ansicht für diese Tabelle. Gewähren Sie dem Benutzer nur eine Auswahl für die Ansicht:

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

Erstellen Sie nun in der zweiten Datenbank den Benutzer und anschließend eine weitere Tabelle und eine Ansicht, die diese Tabelle mit der Ansicht in verbindet d1. Gewähren Sie Auswahl nur für die Ansicht.

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

Starten Sie nun ein neues Abfragefenster und ändern Sie die Anmeldeinformationen für die Anmeldung blat( EXECUTE ASfunktioniert hier nicht). Führen Sie dann im Kontext einer der beiden Datenbanken Folgendes aus, und es sollte einwandfrei funktionieren:

SELECT id FROM d1.dbo.v2;

Diese sollten beide Msg 229-Fehler ergeben:

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

Ergebnisse:

Meldung 229, Ebene 14, Status 5, Zeile 1
Die SELECT-Berechtigung wurde für das Objekt 't1', Datenbank 'd1', Schema 'dbo' verweigert.
Meldung 229, Ebene 14, Status 5, Zeile 3
Die SELECT-Berechtigung wurde für das Objekt 't2', Datenbank 'd2', Schema 'dbo' verweigert.

Aaron Bertrand
quelle
1

Antwort des Community-Wikis, die ursprünglich vom Autor zu der Frage hinzugefügt wurde:

Das habe ich getan:

  1. Erstellt eine Ansicht in DB A und verbindet alle darin enthaltenen Tabellen.
  2. Gewährt SELECTdem Benutzer in dieser Ansicht Zugriff und NICHT auf eine seiner Tabellen. Der Benutzer konnte die Ansicht und nicht die Tabellen erfolgreich abfragen.
  3. Erstellt eine Ansicht in DB B und verknüpft Tabellen in dieser DB zusammen mit der Ansicht in DB A.
  4. Gewährt SELECTdem Benutzer in dieser zweiten Ansicht Zugriff und auch NICHT auf eine Tabelle. Der Benutzer konnte diese endgültige Ansicht erfolgreich abfragen und Daten anzeigen.

Ich finde es seltsam, dass eine Ansicht Tabellen in ihrer Datenbank abfragen kann, wenn der Benutzer keinen direkten Zugriff hat, dies jedoch nicht in Tabellen aus anderen Datenbanken tun kann. Zumindest hat es funktioniert.

user126897
quelle