Ответ 1
Я боюсь, что либо ваше описание, либо ваше представление о цепочке владения неясны, поэтому позвольте мне начать с этого:
"Цепочка прав собственности" просто ссылается на тот факт, что при выполнении хранимой процедуры (или просмотра) на SQL Server текущая исполняемая партия временно приобретает права/разрешения владельца sProc (или владельца схемы sProc) при выполнении этого SQL-код. Таким образом, в случае sProc Пользователь не может использовать эти привилегии для выполнения чего-либо, что код sProc не реализует для них. Обратите внимание, что он никогда не получает Identity владельца, только его права временно (однако, EXECUTE AS... делает это).
Таким образом, типичный подход к обеспечению этого для безопасности заключается в следующем:
-
Поместите все таблицы данных (и все не связанные с безопасностью представления) в свою собственную схему, позвольте ей [данные] (хотя обычно используется [dbo], потому что он уже существует и слишком привилегирован для Пользовательская схема). Убедитесь, что никакие существующие пользователи, схемы или владельцы не имеют доступа к этой [данные] схеме.
-
Создайте схему с именем [exec] для всех sProcs (и/или, возможно, любых представлений безопасности). Убедитесь, что владелец этой схемы имеет доступ к схеме [data] (это легко сделать, если вы сделали dbo владельцем этой схемы).
-
Создайте новую db-роль под названием "Пользователи" и дайте ей EXECUTE доступ к схеме [exec]. Теперь добавьте всех пользователей в эту роль. Убедитесь, что ваши пользователи имеют только права на подключение и не имеют никакого доступа к какой-либо другой схеме, включая [dbo].
Теперь ваши пользователи могут получить доступ к данным только путем выполнения sProcs в [exec]. Они не могут получить доступ к каким-либо другим данным или выполнить любые другие объекты.
Я не уверен, что это отвечает на ваш вопрос (потому что я был не уверен, что вопрос был точно), поэтому не стесняйтесь перенаправлять меня.
Что касается безопасности на уровне строк, вот как я всегда это делаю с помощью схемы безопасности выше:
-
Я всегда реализую безопасность на уровне строк как серию представлений, которые зеркально обертывают каждую таблицу и сравнивают идентификатор пользователя (обычно с Suser_Sname() или одним из других) в список безопасности с ключом из кода безопасности в самой строке. Это Security-Views.
-
Создайте новую схему, называемую [rows], дайте ей доступ владельцу к схеме [data] и ничего больше. Поместите все виды безопасности в эту схему.
-
Отмените доступ владельца [exec] к схеме [data] и вместо этого предоставите ему доступ к данным в схему [rows].
Готово. Теперь безопасность на уровне строк была реализована путем прозрачного перемещения ее между sProcs и таблицами.
Наконец, вот хранимый товар, который я использую, чтобы помочь мне запомнить, как много этого непонятного материала безопасности работает и взаимодействует с ним (oops, исправленная версия кода):
CREATE proc [TestCnxOnly].[spShowProc_Security_NoEX] as
--no "With Execute as Owner" for this version
--create User [UserNoLogin] without login
--Grant connect on database :: TestSecurity to Guest
--alter database TestSecurity set trustworthy on
--Show current user context:
select current_user as current_
, session_user as session
, user_name() as _name
, suser_name() as [suser (sproc)]
, suser_sname() as sname
, system_user as system_
--Execute As Login = 'UserNoLogin'
select current_user as current_
, session_user as session
, user_name() as _name
, suser_name() as [suser (after exec as)]
, suser_sname() as sname
, system_user as system_
EXEC('select current_user as current_
, session_user as session
, user_name() as _name
, suser_name() as [suser (in Exec(sql))]
, suser_sname() as sname
, system_user as system_')
EXEC sp_ExecuteSQL N'select current_user as current_
, session_user as session
, user_name() as _name
, suser_name() as [suser (in sp_Executesql)]
, suser_sname() as sname
, system_user as system_'
--Revert
select current_user as current_
, session_user as session
, user_name() as _name
, suser_name() as [suser (aftr revert)]
, suser_sname() as sname
, system_user as system_
[EDIT: исправленная версия кода)