Jag fruktar att antingen din beskrivning eller din uppfattning om Ownership Chaining är oklar, så låt mig börja med det:
"Ägandekedja" hänvisar helt enkelt till det faktum att när en lagrad procedur (eller vy) körs på SQL Server, förvärvar den för närvarande körande batchen tillfälligt rättigheterna/behörigheterna för sProc:s ägare (eller sProc:s schemaägare) samtidigt som den SQL-koden exekveras. Så i fallet med en sProc kan användaren inte använda dessa privs för att göra något som sProc-koden inte implementerar för dem. Observera särskilt att den aldrig får identiteten för ägaren, endast dess rättigheter, tillfälligt (dock, UTFÖR SOM... gör detta).
Så den typiska metoden för att utnyttja detta för säkerhet är att:
-
Lägg alla datatabeller (och alla icke-säkerhetsvyer också) i sitt eget schema, låt oss kalla det [data] (även om [dbo] vanligtvis används eftersom det redan finns där och för privilegierat för användarens schema). Se till att inga befintliga användare, scheman eller ägare har tillgång till detta [data]-schema.
-
Skapa ett schema som heter [exec] för alla sProcs (och/eller eventuellt alla säkerhetsvyer). Se till att ägaren av detta schema har tillgång till [data]-schemat (detta är enkelt om du gör dbo till ägaren av detta schema).
-
Skapa en ny db-Role som heter "Users" och ge den EXECUTE-åtkomst till [exec]-schemat. Lägg nu till alla användare i den här rollen. Se till att dina användare bara har Connect-rättigheter och inte har beviljad åtkomst till något annat schema, inklusive [dbo].
Nu kan dina användare bara komma åt data genom att köra sProcs i [exec]. De kan inte komma åt någon annan data eller exekvera några andra objekt.
Jag är inte säker på om detta svarar på din fråga (eftersom jag var osäker på vad frågan var exakt), så omdirigera mig gärna.
När det gäller säkerhet på radnivå, så här gör jag alltid med säkerhetsschemat ovan:
-
Jag implementerar alltid säkerhet på radnivå som en serie vyer som speglar varje tabell och jämför användarens identitet (vanligtvis med Suser_Sname() eller en av de andra) med en säkerhetslista som nycklas från en säkerhetskod i själva raden. Dessa är säkerhetsvyerna.
-
Skapa ett nytt schema som heter [rader], ge dess ägare åtkomst till [data]-schemat och inget annat. Lägg alla säkerhetsvyer i det här schemat.
-
Återkalla [exec]-ägarens åtkomst till [data]-schemat och ge den istället dataåtkomst till [rader]-schemat.
Gjort. Nu har säkerhet på radnivå implementerats genom att det transparent glider mellan sProcs och tabellerna.
Slutligen, här är en lagrad anskaffning som jag använder för att hjälpa mig komma ihåg hur mycket av dessa obskyra säkerhetsgrejer som fungerar och interagerar med sig själv (oops, korrigerad version av koden ):
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:korrigerad version av koden)