SQL Server: beri akses pilih ke pengguna dalam tampilan dan bukan dalam tabelnya

11

Saya punya contoh SQL Server 2012 dengan beberapa database. Di salah satunya saya membuat tampilan, yang memilih tabel di lebih dari database.

Saya ingin pengguna dapat memilih tampilan itu, tetapi tidak harus memilih tabelnya. Tampilan dibuat persis karena pengguna tidak dapat memilih tabel.

Saya telah membaca /programming/368414/grant-select-on-a-view-not-base-table dan http://msdn.microsoft.com/en-us/library/ms188676. aspx dan masih tidak berfungsi.

Jika saya melakukan GRANT SELECT TABLE TO USERsemua tabel, pengguna dapat memilih tampilan. Tetapi jika saya mencabut ke meja apa pun, itu gagal.

Ini harus menjadi prosedur yang mudah untuk dilakukan, tetapi saya mengalami kesulitan untuk membuatnya bekerja. Saya pernah melihatnya terjadi sebelumnya (pemilik instance memberi saya akses ke tampilan dan tidak melakukannya ke tabelnya) tetapi saya tidak dapat melakukannya atau menemukan seseorang yang tahu caranya.

Bisakah seseorang memberi saya tutorial tentang cara melakukannya, atau contoh kode?


Ketika pengguna SELECTsmelihat saya menerima pesan:

Izin SELECT ditolak pada objek <TABLE>, basis data <DB>, skema dbo.

Jika saya memberikan pilih ke tabel itu, pesan kesalahan mengubah nama tabel ke tabel lain yang dibaca oleh tampilan.

Hikari
sumber
Komentar bukan untuk diskusi panjang; percakapan ini telah dipindahkan ke obrolan .
Paul White 9

Jawaban:

21

Jika Anda ingin pengguna memilih dari tampilan, mengapa Anda memberikan ke meja? Maksud "mencabut" maksud Anda secara eksplisit mencabut / menolak? Tolak akan menimpa hibah sehingga ada masalah Anda ... Anda harus dapat mencapai ini dengan menambahkan hibah ke tampilan dan tidak melakukan apa pun di atas meja.

Berikut adalah contoh cepat di mana SELECTbelum diberikan secara eksplisit di atas meja, tetapi telah di tampilan. Pengguna dapat memilih dari tampilan tetapi bukan tabel.

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;

Perhatikan bahwa asumsi fooini belum diberikan hak tinggi melalui izin eksplisit pada skema atau basis data, atau melalui peran atau keanggotaan grup.

Karena Anda menggunakan tabel dalam beberapa basis data (maaf saya melewatkan akhir kalimat pertama itu pada awalnya), Anda juga mungkin memerlukan hibah eksplisit pada tabel di dalam database di mana tampilan tidak ada. Untuk menghindari pemberian pilih ke tabel, Anda bisa membuat tampilan di setiap database, dan kemudian bergabung dengan tampilan.

Buat dua database dan login:

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

Dalam database d1, buat pengguna, lalu buat tabel dan tampilan sederhana terhadap tabel itu. Berikan pilihan kepada pengguna hanya terhadap tampilan:

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

Sekarang, di database kedua, buat pengguna, lalu buat tabel lain dan tampilan yang menggabungkan tabel itu ke tampilan di d1. Berikan hanya pilih untuk tampilan.

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

Sekarang luncurkan jendela permintaan baru dan ubah kredensial menjadi untuk login blat( EXECUTE AStidak berfungsi di sini). Kemudian jalankan hal berikut dari konteks basis data mana pun, dan itu akan berfungsi dengan baik:

SELECT id FROM d1.dbo.v2;

Ini seharusnya menghasilkan kesalahan Msg 229:

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

Hasil:

Msg 229, Level 14, Negara 5, Baris 1
Izin SELECT ditolak pada objek 't1', basis data 'd1', skema 'dbo'.
Msg 229, Level 14, Negara 5, Jalur 3
Izin SELECT ditolak pada objek 't2', basis data 'd2', skema 'dbo'.

Aaron Bertrand
sumber
1

Jawaban wiki komunitas awalnya ditambahkan ke pertanyaan oleh penulisnya:

Inilah yang saya lakukan:

  1. Membuat tampilan di DB A, menggabungkan semua tabel di dalamnya.
  2. Diberikan SELECTakses ke pengguna pada tampilan itu, dan BUKAN ke salah satu tabelnya. Pengguna berhasil dapat meminta tampilan dan bukan tabel.
  3. Membuat tampilan di DB B, bergabung dengan tabel di DB ini bersama dengan tampilan di DB A.
  4. Diberikan SELECTakses ke pengguna pada tampilan kedua ini, dan juga BUKAN ke tabel apa pun. Pengguna berhasil dapat meminta tampilan akhir ini dan melihat data.

Saya pikir itu aneh melihat dapat query tabel dalam DB-nya bahwa pengguna tidak memiliki akses langsung tetapi tidak dapat melakukannya dalam tabel dari DB lain. Setidaknya itu berhasil.

pengguna126897
sumber