it-swarm.com.de

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

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 https://stackoverflow.com/questions/368414/grant-select-on-a-view-not-base-table und http://msdn.Microsoft) gelesen .com/de-de/library/ms188676.aspx und es funktioniert immer noch nicht.

Wenn ich für alle Tabellen einen GRANT SELECT TABLE TO USER Führe, 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 SELECTs die Ansicht erhält, erhalte ich die Nachricht:

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

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

11
Hikari

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 Grant, sodass es Ihr Problem gibt. Sie sollten dies erreichen können, indem Sie Grant zur Ansicht hinzufügen und nichts in den Tabellen tun.

Hier ist ein kurzes Beispiel, in dem SELECT nicht explizit für die Tabelle gewährt wurde, sondern für die Ansicht. 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 dies voraussetzt, dass foo 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

Erstellen Sie in der Datenbank d1 Einen Benutzer und anschließend 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 d1 Verbindet. 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 AS Funktioniert 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:

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

21
Aaron Bertrand

Community-Wiki-Antwort ursprünglich von seinem Autor zur Frage hinzugefügt:

Das habe ich getan:

  1. Erstellt eine Ansicht in DB A und verbindet alle darin enthaltenen Tabellen.
  2. Gewährt dem Benutzer in dieser Ansicht SELECT 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 dem Benutzer in dieser zweiten Ansicht SELECT 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.

1
user126897

Wenn Sie Cross database ownership chaining für den Server als datenbankübergreifende Ansichten funktionieren einwandfrei.

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

achte auf die Risiken

0
user2461271