Nadzor dostopa (avtorizacija)
Avtorizacija določa, ali ima uporabnik zadostne pravice, na primer za dostop do določenega vira ali za izvedbo dejanja. Avtorizacija predpostavlja predhodno uspešno preverjanje pristnosti, tj. da je uporabnik prijavljen.
V primerih bomo uporabili objekt razreda Nette\Security\User, ki predstavlja trenutnega uporabnika
in ga dobite s posredovanjem z uporabo vbrizgavanja odvisnosti.
V predstavitvah preprosto pokličite $user = $this->getUser()
.
Za zelo preprosta spletna mesta z administracijo, kjer se pravice uporabnikov ne razlikujejo, je mogoče kot merilo za
avtorizacijo uporabiti že znano metodo isLoggedIn()
. Z drugimi besedami: ko je uporabnik enkrat prijavljen, ima
dovoljenja za vsa dejanja in obratno.
Vloge
Namen vlog je omogočiti natančnejše upravljanje dovoljenj in ostati neodvisen od uporabniškega imena. Takoj ko se uporabnik
prijavi, se mu dodeli ena ali več vlog. Same vloge so lahko preprosti nizi, na primer admin
, member
,
guest
itd. Navedene so v drugem argumentu konstruktorja SimpleIdentity
, in sicer kot niz
ali polje.
Kot merilo avtorizacije bomo zdaj uporabili metodo isInRole()
, ki preveri, ali je uporabnik v dani vlogi:
Kot že veste, odjava uporabnika ne izbriše njegove identitete. Tako metoda getIdentity()
še vedno vrne objekt
SimpleIdentity
, vključno z vsemi dodeljenimi vlogami. Okvir Nette se drži načela „manj kode, več varnosti“,
zato vam pri preverjanju vlog ni treba preverjati, ali je uporabnik tudi prijavljen. Metoda isInRole()
deluje
z učinkovitimi vlogami, tj. če je uporabnik prijavljen, se uporabijo vloge, dodeljene identiteti, če ni prijavljen, se
namesto tega uporabi samodejna posebna vloga guest
.
Avtorizator
Poleg vlog bomo uvedli tudi izraza resource in operation:
- vloga je atribut uporabnika – na primer moderator, urednik, obiskovalec, registrirani uporabnik, administrator, …
- vložek je logična enota aplikacije – članek, stran, uporabnik, element menija, anketa, voditelj, …
- operacija je določena dejavnost, ki jo uporabnik lahko ali ne sme opraviti z virem – ogled, urejanje, brisanje, glasovanje, …
Avtorizator je objekt, ki odloča o tem, ali ima določena role dovoljenje za izvajanje določene operacije
z določenim izdelkom. To je objekt, ki implementira vmesnik Nette\Security\Authorizator s samo eno metodo
isAllowed()
:
Avtorizator dodamo v konfiguracijo kot storitev vsebnika DI:
V nadaljevanju je prikazan primer uporabe. Upoštevajte, da tokrat kličemo metodo
Nette\Security\User::isAllowed()
, in ne avtorizatorjeve, zato ni prvega parametra $role
. Ta metoda
zaporedno kliče MyAuthorizator::isAllowed()
za vse uporabniške vloge in vrne true, če ima vsaj ena od njih
dovoljenje.
Oba argumenta sta neobvezna, njuna privzeta vrednost pa pomeni vse.
Dovoljenje ACL
Nette ima vgrajeno implementacijo avtorizatorja, razred Nette\Security\Permission, ki ponuja lahek in prilagodljiv sloj ACL (Access Control List) za nadzor dovoljenj in dostopa. Pri delu s tem razredom določimo vloge, vire in posamezna dovoljenja. Vloge in viri lahko tvorijo hierarhije. Za razlago bomo prikazali primer spletne aplikacije:
guest
: obiskovalec, ki ni prijavljen, lahko bere in brska po javnem delu spleta, tj. bere članke, komentira in glasuje v anketahregistered
: prijavljeni uporabnik, ki lahko poleg tega objavlja komentarjeadmin
: lahko upravlja članke, komentarje in ankete
Tako smo določili določene vloge (guest
, registered
in admin
) in omenili vire
(article
, comments
, poll
), do katerih lahko uporabniki dostopajo ali izvajajo dejanja
(view
, vote
, add
, edit
).
Ustvarimo primerek razreda Permission in opredelimo vloge. Uporabiti je mogoče dedovanje vlog, kar zagotavlja, da lahko
na primer uporabnik z vlogo admin
počne to, kar lahko počne običajni obiskovalec spletnega mesta (in seveda
še več).
Zdaj bomo opredelili seznam vsebin, do katerih lahko dostopajo uporabniki:
Viri lahko uporabljajo tudi dedovanje, na primer, dodamo lahko $acl->addResource('perex', 'article')
.
In zdaj najpomembnejša stvar. Med njimi bomo določili pravila, ki določajo, kdo lahko kaj počne:
Kaj pa, če želimo nekomu preprečiti dostop do vira?
Ko smo ustvarili nabor pravil, lahko preprosto zastavimo poizvedbe o avtorizaciji:
Enako velja za registriranega uporabnika, ki pa lahko tudi komentira:
Administrator lahko ureja vse razen anket:
Dovoljenja se lahko ocenjujejo tudi dinamično, odločitev pa lahko prepustimo lastnemu povratnemu klicu, ki so mu posredovani vsi parametri:
Kako pa rešiti situacijo, ko imena vlog in virov ne zadoščajo, torej bi radi določili, da lahko na primer vloga
registered
ureja vir article
le, če je njegov avtor? Namesto nizov bomo uporabili predmete, vloga bo
predmet Nette\Security\Role in vir Nette\Security\Resource. Njuni metodi
getRoleId()
oziroma getResourceId()
bosta vrnili izvirne nize:
Zdaj pa ustvarimo pravilo:
Po ACL poizvedujemo tako, da posredujemo predmete:
Vloga lahko podeduje eno ali več drugih vlog. Toda kaj se zgodi, če ima en prednik določeno dejanje dovoljeno, drugi pa prepovedano? Takrat pride v poštev teža vloge – zadnja vloga v nizu podedovanih vlog ima največjo težo, prva pa najmanjšo:
Vloge in vire je mogoče tudi odstraniti (removeRole()
, removeResource()
), pravila je mogoče tudi
razveljaviti (removeAllow()
, removeDeny()
). Polje vseh neposrednih starševskih vlog vrne
getRoleParents()
. Ali dve entiteti dedujeta druga od druge, vrne roleInheritsFrom()
in
resourceInheritsFrom()
.
Dodaj kot storitev
ACL, ki smo ga ustvarili, moramo dodati v konfiguracijo kot storitev, da ga lahko uporablja objekt $user
, tj. da
ga lahko uporabimo v kodi, na primer $user->isAllowed('article', 'view')
. V ta namen bomo zanj napisali
tovarno:
In jo bomo dodali v konfiguracijo:
V predstavitvah lahko nato preverite dovoljenja v metodi startup()
, na primer: