SQL Server: надайте вибір вибору користувачеві в представленні, а не в його таблицях


11

У мене є екземпляр SQL Server 2012 з кількома базами даних. В одному з них я створив представлення, яке вибирає таблиці більш ніж у базі даних.

Я хочу, щоб користувач міг вибрати цей вид, але він не повинен вибирати його таблиці. Представлення створено саме тому, що користувач не може вибрати таблиці.

Я прочитав /programming/368414/grant-select-on-a-view-not-base-table та http://msdn.microsoft.com/en-us/library/ms188676. aspx і досі не працює.

Якщо я виконую GRANT SELECT TABLE TO USERвсі таблиці, користувач може вибрати перегляд. Але якщо я відкликаю будь-який стіл, це не вдається.

Це має бути простою процедурою, але у мене виникають проблеми, щоб змусити її працювати. Я бачив, як це відбувалося раніше (власник екземпляра надав мені доступ до перегляду і не робив це до своїх таблиць), але я не в змозі це зробити або знайти когось, хто знає як.

Чи міг би хтось надати мені підручник про те, як це зробити, або приклад коду?


Коли користувач SELECTsпереглядає, я отримую повідомлення:

У дозволі SELECT було відмовлено на об'єкті <TABLE>, базі даних <DB>, схемі dbo.

Якщо я надаю вибір для цієї таблиці, повідомлення про помилку змінює ім’я таблиці на іншу таблицю, яку читає подання.


Коментарі не для розширеного обговорення; ця розмова була переміщена до чату .
Пол Білий 9

Відповіді:


21

Якщо ви хочете, щоб користувачі вибирали з перегляду, чому ви надаєте таблицю? Під "відкликати" ви маєте на увазі явну відкликання / заперечення? Заборонити буде перекривати грант, тож у вас є проблема ... ви повинні мати можливість це додати, додавши грант у подання, і нічого не роблячи на столах.

Ось короткий приклад, коли SELECTявно не було надано на стіл, але воно було переглянуте. Користувач може вибрати з перегляду, але не таблиці.

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;

Зауважте, що цим припущенням fooне надано підвищених привілеїв за допомогою явних дозволів на схемі чи базі даних або через членство в ролі чи групі.

Оскільки ви використовуєте таблиці в декількох базах даних (вибачте, що спочатку я пропустив кінець цього першого речення), вам також можуть знадобитися явні дотації на таблицях (таблицях) в базі даних, де перегляд не існує. Щоб уникнути надання вибору до таблиці (таблиць), ви можете створити представлення даних у кожній базі даних, а потім приєднатись до переглядів.

Створіть дві бази даних та логін:

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

У базі даних d1створіть користувача, а потім створіть таблицю та простий вигляд проти цієї таблиці. Надайте користувачеві вибір лише проти перегляду:

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

Тепер у другій базі даних створіть користувача, а потім створіть іншу таблицю та представлення, яке приєднує цю таблицю до представлення в d1. Дозволити вибір лише для подання.

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

Тепер запустіть нове вікно запитів та змініть облікові дані для входу blat( EXECUTE ASтут не працює). Потім запустіть наступне з контексту будь-якої бази даних, і воно повинно працювати нормально:

SELECT id FROM d1.dbo.v2;

Вони мають призвести до помилок Msg 229:

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

Результати:

Msg 229, рівень 14, стан 5, рядок 1
В дозволі SELECT було відмовлено на об'єкті 't1', базі даних 'd1', схемі 'dbo'.
Msg 229, рівень 14, стан 5, рядок 3
В дозволі SELECT було відмовлено на об'єкті 't2', базі даних 'd2', схемі 'dbo'.


1

Відповідь вікі спільноти спочатку додав на запитання її автор:

Ось що я зробив:

  1. Створив подання в БД А, об'єднавши всі таблиці в ньому.
  2. Наданий користувачеві SELECTдоступ до цього перегляду, а НЕ до будь-якої його таблиці. Користувачеві вдалося запитувати перегляд, а не таблиці.
  3. Створив подання в БД B, об'єднавши таблиці в цій БД разом з представленням у БД А.
  4. Надано користувачеві SELECTдоступ до цього другого перегляду, а також НЕ до будь-якої таблиці. Користувачеві вдалося здійснити запит на цей остаточний вигляд та переглянути дані.

Я думаю, що дивним виглядом є можливість запиту таблиць у своїй БД, щоб користувач не мав прямого доступу, але не в змозі це зробити в таблицях з інших БД. Принаймні це спрацювало.


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.