Як додати користувача з доступом до одного перегляду?


14

Я працюю з MSSQL Server Management Studio 2008 і мені потрібно викрити перегляд третьої сторони для їх узгодження даних. Я створив відповідний вигляд, але у мене виникли проблеми зі створенням користувача та наданням користувачеві відповідних дозволів для вибору з представлення даних.

Я слідував за майстрами для створення логіна та користувача, а потім додав свій погляд у розділ Securables, коли прапорець із дозволом встановлено для вибору. Все здавалося прекрасним, але коли я ввійшов у систему як цей користувач і намагався зробити "Select * from MyViewName", мені сказали, що в дозволі на вибір заборонено.

Я просто відтворив користувача (на цей раз просто використовуючи SQL замість майстра) і явно надав дозволу на вибір, і тепер він дає мені помилку: 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.(я не знаю, чому він намагається отримати доступ до незв'язаної бази даних ...)

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


3
Чи базуються базові таблиці перегляду в інших базах даних? Якщо так, вам доведеться мати справу з ланцюжком власності. Також переконайтеся, що у вас зараз контекст бази даних встановлений на потрібну базу даних.
Томас Стрінгер

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

Відповіді:


16

Будь ласка, не використовуйте для цього інтерфейс користувача. Це заплутаний безлад.

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

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

Ось EDIT - це приклад сценарію, який призведе до вказаної вами помилки.

Спочатку створіть деяку таблицю у зв’язаному_db:

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

Тепер створіть відносно обмежений логін:

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

Тепер створіть базу даних, де буде переглядати представлення даних, і додайте логін як користувач:

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

Тепер створіть функцію, яка буде посилатися на таблицю в іншій базі даних, і синонім до іншої таблиці:

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

Тепер створіть локальну таблицю:

CREATE TABLE dbo.PaymentDetails
(
  PaymentID INT
);
GO

Тепер створити уявлення , яке посилається на таблицю, то функція і синонім, і грант SELECTна 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

Тепер спробуйте виконати як usernameі виберіть з представлення лише локальний стовпець:

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

Результат:

Повідомлення 916, рівень 14, стан 1, рядок 3
Основне "ім'я користувача" сервера не в змозі отримати доступ до бази даних "не пов'язано_db" в поточному контексті безпеки.

Тепер змініть вигляд, щоб не посилатися на будь-які зовнішні об’єкти, і запустіть вищезгадане SELECT, і воно працює:

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

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

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 не просто намагатиметься отримати доступ unrelated_dbдля задоволення від цього ... повинен бути якийсь зв’язок із цією базою даних з виду, який ви намагаєтеся використовувати. На жаль, якщо ми не можемо побачити визначення перегляду та більше деталей про об'єкти, до яких він торкається, ми можемо лише спекулювати. Дві основні речі, які я можу придумати, - це синоніми чи функції, які використовують імена з трьох частин, але перегляд фактичних сценаріїв дасть нам набагато краще уявлення, а не вгадування. :-)

Ви також можете перевірити sys.dm_sql_referenced_entities, проте ця функція не повертає нічого корисного у наведеному вище прикладі.


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

Ви можете перевірити це, виконавши наступне:

execute as user = 'YourTpvUser'
go

select *
from YourView

revert
go

Мабуть, це не надає рекурсивних пільг. Користувачеві дозволено вибирати з "YourView", але якщо "YourView" залежить від інших відносин / баз даних, він вийде з ладу: головний сервер "YourTpvUser" не може отримати доступ до бази даних "OtherDb" у поточному контексті безпеки.
lilalinux
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.