Come aggiungere un utente con accesso a una singola vista?


14

Sto lavorando con MSSQL Server Management Studio 2008 e ho bisogno di esporre una vista a terzi per la loro riconciliazione dei dati. Ho creato la vista appropriata ma sto riscontrando problemi nella creazione di un utente e nel dare a quell'utente le autorizzazioni appropriate per selezionare dalla vista.

Ho seguito le procedure guidate per la creazione di un account di accesso e un utente e quindi ho aggiunto la mia vista nella sezione Titoli con la casella di controllo selezionata per selezionare. Tutto sembrava a posto ma quando ho effettuato l'accesso come quell'utente e ho provato a fare un "Select * da MyViewName", mi è stato detto che l'autorizzazione di selezione era stata negata.

Ho appena ricreato l'utente (questa volta solo usando SQL invece della procedura guidata) e 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.ho esplicitamente concesso autorizzazioni di selezione e ora mi sta dando l'errore: (Non so perché sta provando ad accedere al database non correlato ...)

Non so davvero dove andare da qui. Ancora una volta, fondamentalmente tutto ciò di cui ho bisogno è creare un utente che posso dare a terzi per farli connettersi al nostro database e selezionare da questa vista.


3
La vista fa riferimento a tabelle di base in altri database? In tal caso, dovrai occuparti del concatenamento della proprietà. Inoltre, assicurarsi di disporre attualmente del contesto del database impostato sul database desiderato.
Thomas Stringer,

C'è un modo per vedere le dipendenze per una vista? Voglio dire, per quanto ne so, tutto dalla vista dovrebbe essere contenuto nel database principale. La vista contiene solo tre campi, due provenienti da una tabella dei dettagli di pagamento e uno proveniente da un'unione alla tabella dei dettagli dell'account ma entrambe le tabelle si trovano nello stesso database (e nello stesso database della vista).
velojason,

Risposte:


16

Non utilizzare l'interfaccia utente per questo. È un casino confuso.

Mi sembra che quello che vuoi sia creare un utente in un database, per un login specifico, che abbia solo le autorizzazioni per selezionare da una vista. Quindi, poiché hai già creato il login:

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

EDIT qui è un esempio di uno script che porterà all'errore menzionato.

Innanzitutto, crea una tabella in unrelated_db:

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

Ora crea un accesso relativamente limitato:

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

Ora crea un database in cui vivrà la vista e aggiungi il login come utente:

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

Ora crea una funzione che farà riferimento alla tabella nell'altro database e un sinonimo all'altra tabella:

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

Ora crea una tabella locale:

CREATE TABLE dbo.PaymentDetails
(
  PaymentID INT
);
GO

Ora crea una vista che faccia riferimento alla tabella, alla funzione e al sinonimo e concedi SELECTa username:

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

Ora prova a eseguire as usernamee seleziona solo la colonna locale dalla vista:

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

Risultato:

Messaggio 916, livello 14, stato 1, riga 3
L'entità server "nome utente" principale non è in grado di accedere al database "unrelated_db" nel contesto di protezione corrente.

Ora cambia la vista per non fare riferimento a nessun oggetto esterno ed esegui di SELECTnuovo quanto sopra e funziona:

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

A corto di mostrarci gli script per i dettagli di pagamento, i dettagli dell'account e gli oggetti MyView, forse puoi farci sapere se questa query restituisce risultati. Puoi trovare riferimenti a vari oggetti attraverso la vista del catalogo sys.sql_expression_dependencies, ma questa vista non è perfetta - credo che dipenda da tutte le viste da aggiornare (nel caso in cui le viste facciano riferimento ad altre viste, ad esempio, o lo schema sottostante sia cambiato) in ordine per essere precisi.

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 non tenterà solo di accedervi unrelated_dbper divertimento ... deve esserci un legame con quel database dalla vista che stai cercando di usare. Sfortunatamente se non riusciamo a vedere la definizione della vista e ulteriori dettagli sugli oggetti che tocca, tutto ciò che possiamo fare è speculare. Le due cose principali a cui riesco a pensare sono i sinonimi o le funzioni che usano nomi in tre parti, ma vedere gli script reali ci darà un'idea molto migliore invece di indovinare. :-)

Potresti anche voler controllare sys.dm_sql_referenced_entities, tuttavia questa funzione non restituisce nulla di utile nell'esempio sopra.


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

Puoi provarlo eseguendo le seguenti operazioni:

execute as user = 'YourTpvUser'
go

select *
from YourView

revert
go

Apparentemente questo non concede in modo ricorsivo i privilegi. L'utente può selezionare da "YourView" ma se "YourView" dipende da altre relazioni / database, fallirà: l'entità server "YourTpvUser" non è in grado di accedere al database "OtherDb" nel contesto di sicurezza corrente.
lilalinux,
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.