SQL Server: concedere l'accesso selezionato a un utente in una vista e non nelle sue tabelle


11

Ho un'istanza di SQL Server 2012 con alcuni database. In uno di essi ho creato una vista che seleziona le tabelle in più di un database.

Voglio che un utente sia in grado di selezionare quella vista, ma non deve selezionare le sue tabelle. La vista è stata creata esattamente perché l'utente non può selezionare le tabelle.

Ho letto /programming/368414/grant-select-on-a-view-not-base-table e http://msdn.microsoft.com/en-us/library/ms188676. aspx e ancora non funziona.

Se faccio un GRANT SELECT TABLE TO USERa tutti i tavoli, l'utente è in grado di selezionare la vista. Ma se revoco a qualsiasi tavolo, fallisce.

Questa dovrebbe essere una procedura facile da fare, ma ho problemi a farlo funzionare. L'ho visto accadere prima (il proprietario di un'istanza mi ha dato accesso a una vista e non l'ha fatto ai suoi tavoli) ma non sono in grado di farlo o di trovare qualcuno che sappia come.

Qualcuno potrebbe fornirmi un tutorial su come farlo, o un esempio di codice?


Quando l'utente SELECTsvisualizza la vista ricevo il messaggio:

L'autorizzazione SELECT è stata negata su oggetto <TABLE>, database <DB>, schema dbo.

Se concedo la selezione a quella tabella, il messaggio di errore modifica il nome della tabella in un'altra tabella visualizzata dalla vista.


I commenti non sono per una discussione estesa; questa conversazione è stata spostata in chat .
Paul White 9

Risposte:


21

Se desideri che gli utenti selezionino dalla vista, perché concedi alla tabella? Con "revoca" intendi esplicitamente revocare / negare? Nega sovrascriverà la concessione, quindi c'è il tuo problema ... dovresti essere in grado di farlo aggiungendo la sovvenzione alla vista e non facendo nulla in alcun modo sui tavoli.

Ecco un breve esempio in cui SELECTnon è stato concesso esplicitamente sulla tabella, ma è stato visualizzato. L'utente può selezionare dalla vista ma non dalla tabella.

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;

Si noti che ciò presuppone che foonon siano stati concessi privilegi elevati tramite autorizzazioni esplicite sullo schema o sul database o tramite l'appartenenza a ruoli o gruppi.

Dato che stai utilizzando le tabelle in più database (mi dispiace, all'inizio, ho perso la fine della prima frase), potresti anche aver bisogno di sovvenzioni esplicite sulle tabelle nel database in cui la vista non esiste. Per evitare di concedere la selezione alle tabelle, è possibile creare una vista in ciascun database e quindi unire le viste.

Crea due database e un login:

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

Nel database d1, creare un utente, quindi creare una tabella e una vista semplice rispetto a quella tabella. Concedi la selezione all'utente solo per la vista:

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

Ora, nel secondo database, creare l'utente, quindi creare un'altra tabella e una vista che unisce quella tabella alla vista in d1. Concedi selezionare solo per la vista.

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

Ora avvia una nuova finestra di query e modifica le credenziali per l'accesso blat( EXECUTE ASnon funziona qui). Quindi eseguire quanto segue dal contesto di entrambi i database e dovrebbe funzionare correttamente:

SELECT id FROM d1.dbo.v2;

Questi dovrebbero entrambi generare errori 229:

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

risultati:

Messaggio 229, livello 14, stato 5, riga 1
L'autorizzazione SELECT è stata negata sull'oggetto 't1', database 'd1', schema 'dbo'.
Messaggio 229, livello 14, stato 5, riga 3
L'autorizzazione SELECT è stata negata sull'oggetto 't2', database 'd2', schema 'dbo'.


1

Risposta wiki della comunità originariamente aggiunta alla domanda dal suo autore:

Questo è quello che ho fatto:

  1. Creata una vista nel DB A, unendo tutte le tabelle in essa contenute.
  2. Concesso l' SELECTaccesso all'utente su quella vista e NON a nessuna delle sue tabelle. L'utente è stato in grado di interrogare correttamente la vista e non le tabelle.
  3. Creata una vista nel DB B, unendo le tabelle in questo DB insieme alla vista nel DB A.
  4. Ha concesso l' SELECTaccesso all'utente in questa seconda vista, e NON anche a nessuna tabella. L'utente è stato in grado di interrogare correttamente questa vista finale e visualizzare i dati.

Penso che sia strano che una vista sia in grado di interrogare le tabelle nel suo DB che l'utente non ha accesso diretto ma non è in grado di farlo nelle tabelle di altri DB. Almeno ha funzionato.


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.