2013-07-23 2 views
0

Мы используем хранимые процедуры, чтобы ограничить доступ некоторых пользователей нашей базы данных. Им нужен доступ к определенным частям базы данных (а не только к таблицам/представлениям, но также к определенным строкам), и sproc должен проверить, разрешено ли пользователю видеть строки таблицы, которые он запрашивает.Хранение DATABASE_PRINCIPAL_ID в таблице sql server

Для сохранения правил авторизации, мы планируем использовать таблицу dbo.AuthRules так:

|ID|UserId |AccessFrom |AccessTo | ... 
=============================================== 
| 1|  1| 01.01.2013 | 31.12.2013 | ... 
| 2|  2| 31.05.2012 | 31.12.2015 | ... 

Хранимая процедура будет запросить эту таблицу, чтобы проверить, если текущий пользователь имеет доступ к запрашиваемым данным. Чтобы сделать это ясно: Мы не можем просто использовать GRANT PERMISSION, потому что нам нужны мелкие правила доступа к строкам в БД.

Мы не уверены в колонке UserId. Лучшим решением будет какой-то внешний ключ для системного представления sys.database_principals, но нет внешних ключей к просмотру.

  • Если мы просто хранить principal_id столбец sys.database_principals, без каких-либо ограничений?
  • Было бы лучше хранить столбец name вместо principal_id?
  • Существуют ли другие варианты хранения ссылки на пользователя БД?
+2

Параметр 'sid' является более стабильным, чем либо имя/ID –

+0

Но' sid' устанавливается только для пользователей Windows Auth, верно? Поэтому в случае пользователей, прошедших проверку подлинности SQL Server, нам все равно придется использовать 'ID' или' name'. – cheeesus

+1

нет, каждый логин получает SID. Пользователи Windows получают SID, который соответствует их SID окон, тогда как логины SQL получают отдельно созданный. См. [Принципы] (http://msdn.microsoft.com/en-us/library/ms181127.aspx): «** У каждого ** принципала есть идентификатор безопасности (SID)». (Мой акцент), прежде чем он затем описывает различные типы руководителей –

ответ

1

В: Должен ли мы просто хранить столбец main_id sys.database_principals без каких-либо ограничений?

A: Если вы оцениваете только решение на основе ограничений, у вас действительно нет выбора. Однако, если вы готовы написать триггер, это будет способ, по крайней мере, «фактически» создать ограничение. В противном случае вам придется ссылаться на таблицу sysowners, и это невозможно без какого-либо взлома.

Вопрос: Было бы лучше сохранить столбец имен вместо main_id?

A: Чтобы ответить на этот вопрос, вы должны задать вопрос «что-то». Что делать, если изменяется main_id? Что, если имя изменится? Как насчет обновлений/удалений? У меня всегда было бы решение на основе id.

В: Существуют ли другие варианты хранения ссылки на пользователя БД?

A: Как указано в ответе # 1, я не думаю, что есть какие-либо возможности, кроме создания триггера ...

1

Рассмотрим этого метода проектирования.

USE "master"; 

-- Create our test logins (don't forget to tidy these up later!) 
CREATE LOGIN "batman" 
    WITH PASSWORD = N'' 
    , CHECK_EXPIRATION = OFF 
    , CHECK_POLICY = OFF; 

CREATE LOGIN "robin" 
    WITH PASSWORD = N'' 
    , CHECK_EXPIRATION = OFF 
    , CHECK_POLICY = OFF; 

USE "playdb"; 

-- Create the corresponding users 
CREATE USER "batman" 
    FOR LOGIN "batman"; 

CREATE USER "robin" 
    FOR LOGIN "robin"; 

-- Grant them some select permissions 
EXEC sp_addrolemember N'db_datareader', N'batman'; 
EXEC sp_addrolemember N'db_datareader', N'robin'; 

-- Create our "user access" table 
DECLARE @users table (
    username sysname NOT NULL 
, access_from date NOT NULL DEFAULT '1900-01-01' -- Deliberately not allowing nulls and setting the widest possible value range 
, access_to date NOT NULL DEFAULT '9999-12-31' -- this will make our queries so much easier! 
); 

-- Give one user full permissions 
INSERT INTO @users (username) 
    VALUES ('batman'); 

-- Limit what this chappy can see 
INSERT INTO @users (username, access_from, access_to) 
    VALUES ('robin', '2011-01-01', '2012-01-01'); 

-- Example data table 
DECLARE @data table (
    date_field date NOT NULL 
); 
-- ...with example data 
INSERT INTO @data (date_field) 
    VALUES ('2010-01-01') 
     , ('2011-01-01') 
     , ('2012-01-01') 
     , ('2012-01-01') 
     , ('2013-01-01') 
     , ('2014-01-01'); 

-- Let's mimic our full access user 
SETUSER 'batman'; 

SELECT System_User As current_username 
    , * 
FROM @data As data 
WHERE EXISTS (-- Limit the records to only those this user is allowed to see 
     SELECT * 
     FROM @users 
     WHERE username = System_User 
     AND data.date_field >= access_from 
     AND data.date_field < access_to 
     ); 

SETUSER; -- Reset user 

-- Imitate the chap with restricted access 
SETUSER 'robin'; 

-- Exacty same query as before 
SELECT System_User As current_username 
    , * 
FROM @data As data 
WHERE EXISTS (
     SELECT * 
     FROM @users 
     WHERE username = System_User 
     AND data.date_field >= access_from 
     AND data.date_field < access_to 
     ); 
+0

Спасибо, я думаю, что это пример реализации того, что я имел в виду, но я не уверен, что вы думаете. Вы сохраняете свойство 'name' пользователя, которое менее стабильно, чем его' ID' или его 'sid' .. – cheeesus

+1

Имя пользователя прозрачное и портативное (новые ID/SIDS, если вам нужно воссоздать пользователей на новом сервере, например, dev/qa/live). Это может быть имя пользователя SQL, имя пользователя authed username или windows auth, что означает, что это очень тоже гибкий! – gvee

+0

Хорошая точка, спасибо! – cheeesus

Смежные вопросы