Hvorfor er rækkeniveausikkerhed vigtig?
Før SQL Server 2016 var sikkerhed på tabelniveau det laveste sikkerhedsniveau som standard for en database. Med andre ord kan en bruger være begrænset til at få adgang til en tabel som helhed. Men i nogle tilfælde har vi brug for, at brugerne har adgang til en tabel, men ikke til bestemte rækker i tabellen. Før SQL Server 2016 krævede dette, at brugerdefinerede lagrede procedurer blev skrevet for at levere en sådan finmasket sikkerhed. Sådanne lagrede procedurer er imidlertid tilbøjelige til SQL-injektion og andre sikkerhedsforbehold.
Brug af SQL Server Row Level Security-funktion i praksis
SQL Server 2016 introducerede en ny sikkerhedsfunktion på rækkeniveau, som giver brugerne mulighed for at få adgang til en tabel, men begrænser dem til at få adgang til specifikke rækker i den tabel. Lad os tage et kig på, hvordan dette kan bruges praktisk.
Beskrivelse
Der er fire trin til implementering af sikkerhed på rækkeniveau i SQL Server.
- Giv Select-tilladelser til brugerne på bordet, hvor du vil implementere sikkerhed på rækkeniveau.
- Dernæst skal du skrive en inline-tabelværdifunktion, der indeholder et filterprædikat. Tilføj filterlogikken til filterprædikatet.
- Til sidst skal du binde filterprædikatet, som du oprettede i andet trin, til en sikkerhedspolitik.
- Test sikkerhedsfunktionen på rækkeniveau.
Før vi udfører ovenstående trin, skal vi oprette en dummy-database med nogle dummy-poster. Udfør følgende script for at gøre det:
CREATE DATABASE UniversityGOUSE UniversityGOUSE UniversityCREATE TABEL Personer(Id INT PRIMÆR NØGLEIDENTITET(1,1),Navn VARCHAR (50),Rolle VARCHAR (50))GOUSE UniversitetINDSÆT I Personer VÆRDIER ('Sally', 'Principal' )INSERT INTO Persons VALUES ('Edward', 'Student' )INSERT INTO Persons VALUES ('Jon', 'Student' )INSERT INTO Persons VALUES ('Scot', 'Student')INSERT INTO Persons VALUES ('Ben', 'Student' ) INSERT INTO Persons VALUES ('Isabel', 'Teacher' )INSERT INTO Persons VALUES ('David', 'Lærer' )INSERT INTO Persons VALUES ('Laura', 'Lærer' )INSERT INTO Persons VALUES ('Jean', 'Lærer' ')INSERT INTO Persons VALUES ('Francis', 'Lærer' )
I scriptet opretter vi en dummy-database "Universitet". Dernæst udfører vi scriptet, der opretter en tabel med navnet "Personer". Hvis du ser på tabeldesignet, kan du se, at det indeholder tre kolonner Id, Name og Rolle. Id-kolonnen er den primære nøglekolonne med IDENTITY-begrænsning. Kolonnen Navn indeholder navnet på personen, og kolonnen Rolle indeholder personens rolle. Til sidst indsatte vi 10 poster i tabellen Personer. Tabellen har 1 rektor, 4 lærere og 5 elever.
Lad os udføre en simpel SELECT-sætning for at se poster i tabellen:
Brug UniversitySELECT * FROM Persons
Resultatet ser således ud:
Vi ønsker, at brugeren ved navn Principal skal have adgang til alle rækkerne i tabellen Personer. På samme måde bør en lærer kun have adgang til lærerens optegnelser, mens studerende kun skal have adgang til elevoptegnelserne. Dette er et klassisk tilfælde af sikkerhed på rækkeniveau.
For at implementere rækkeniveausikkerheden vil vi følge de trin, vi diskuterede tidligere.
Trin 1:Giv udvalgte tilladelser til brugere på bordet
Lad os oprette tre brugere med rollerne Rektor, Lærer og Elev og give dem SELECT-adgang til disse brugere i tabellen Personer. Udfør følgende script for at gøre det:
OPRET BRUGER Rektor UDEN LOGIN;GOGRANT SELECT ON Personer TIL Lærer;GOGRANT SELECT ON Personer TIL Studerende;GOGRANT SELECT ON Personer TIL Studerende;GOGRANT SELECT ON Personer TIL Studerende;GOGRANTTrin 2:Oprettelse af filterprædikat
Når brugerne har fået tilladelser, er næste trin at oprette et filterprædikat.
Følgende script gør det:
Brug UniversityGOCREATE FUNCTION dbo.fn_SP_Person(@Role AS sysname) RETURNS TABLEWITH SCHEMABINDINGAS RETURN SELECT 1 AS fn_SP_Person_output -- Prædikatlogik WHERE @Role =USER_NAME() ELLER USER_NAME>()';Filterprædikatet er oprettet inde i en inline-tabelvurderet funktion og tager brugerens rolle som en parameter. Det returnerer de poster, hvor rolleværdien, der er sendt som en parameter, matcher rolleværdien i kolonnen Rolle. Eller hvis brugerrollen er 'Principal', returneres alle rollerne. Hvis du ser på prædikatfilteret, finder du ikke det tabelnavn, som vi laver filteret for. Filterprædikatet er forbundet til tabellen via den sikkerhedspolitik, som vi vil se i næste trin.
Trin 3:Oprettelse af en sikkerhedspolitik
Udfør følgende script for at oprette en sikkerhedspolitik for filterprædikatet, som vi oprettede i sidste trin:
Brug UniversityGoCREATE SIKKERHEDSPOLITIK RoleFilterADD FILTER PREDICATE dbo.fn_SP_Person(Role)ON dbo.PersonsWITH (STATE =ON);GOI sikkerhedspolitikken har vi blot tilføjet det filterprædikat, vi oprettede, til tabellen Personer. For at aktivere politikken skal "STATE"-flaget sættes til ON.
Trin 4:Test af sikkerhed på rækkeniveau
Vi udførte alle de nødvendige trin for at håndhæve sikkerhed på rækkeniveau på tabellen Personer i universitetets database. Lad os først prøve at få adgang til posterne i tabellen Personer via standardbruger. Udfør følgende script:
Brug UniversitySELECT * FROM Persons;GODu vil ikke se noget i outputtet, da standardbrugeren ikke kan få adgang til tabellen Personer.
Lad os skifte til elevbrugeren, som vi oprettede tidligere, og prøve at VÆLGE poster fra tabellen Personer:
EXECUTE AS USER ='Student';Brug UniversitySELECT * FROM Personer; -- Kun elevoptegnelserREVERT;GOI scriptet ovenfor skifter vi til 'Student'-brugeren, valgte poster fra tabellen Personer og vender tilbage til standardbrugeren. Outputtet ser således ud:
Du kan se, at på grund af sikkerheden på rækkeniveau, vises kun poster, hvor kolonnen Rolle har værdien Elev.
På samme måde vil brugeren Lærer kun have adgang til poster, hvor Rolle-kolonnen har værdien Lærer. Udfør følgende script for at bekræfte dette:
EXECUTE AS USER ='Lærer';Brug UniversitySELECT * FROM Personer; -- All RecordsREVERT;GOI outputtet vil du have følgende poster:
Til sidst implementerede vi i vores filterprædikat logikken om, at brugeren Principal kan få adgang til alle posterne. Lad os bekræfte dette ved at udføre følgende forespørgsel:
EXECUTE AS USER ='Principal';Brug UniversitySELECT * FROM Personer; -- All RecordsREVERT;GOI outputtet vil du se alle posterne som vist nedenfor:
Konklusion
Sikkerhedsfunktionen på rækkeniveau er yderst nyttig, når du ønsker, at brugere skal have finmasket adgang til specifikke data. Sikkerhedsfunktionen på rækkeniveau involverer dog en inline-tabel-vurderet funktion, som kan få dig til at få et præstationshit.
Som en tommelfingerregel, hvis du planlægger at bruge en simpel WHERE-sætning i prædikatfunktionen, bør din præstation ikke blive påvirket. På den anden side bør komplekse join-sætninger, der involverer opslagstabeller, undgås, når du har implementeret sikkerhed på rækkeniveau.