Erişim Kontrolü (Yetkilendirme)
Yetkilendirme, bir kullanıcının örneğin belirli bir kaynağa erişmek veya bir eylemi gerçekleştirmek için yeterli ayrıcalıklara sahip olup olmadığını belirler. Yetkilendirme, daha önce başarılı bir kimlik doğrulaması yapıldığını, yani kullanıcının oturum açtığını varsayar.
Örneklerde, mevcut kullanıcıyı temsil eden ve bağımlılık
enjeksiyonu kullanarak geçirerek elde ettiğiniz Nette\Security\User sınıfından bir nesne kullanacağız.
Sunucularda $user = $this->getUser()
adresini çağırmanız yeterlidir.
Kullanıcı haklarının ayırt edilmediği çok basit yönetimli web siteleri için, zaten bilinen yöntemi bir yetkilendirme
kriteri olarak kullanmak mümkündür isLoggedIn()
. Başka bir deyişle: bir kullanıcı oturum açtığında, tüm
eylemler için izinlere sahip olur ve bunun tersi de geçerlidir.
Roller
Rollerin amacı daha hassas bir izin yönetimi sunmak ve kullanıcı adından bağımsız kalmaktır. Kullanıcı oturum açar
açmaz, kendisine bir veya daha fazla rol atanır. Rollerin kendileri basit dizeler olabilir, örneğin, admin
,
member
, guest
, vb. Bunlar SimpleIdentity
kurucusunun ikinci argümanında bir dize ya da
dizi olarak belirtilir.
Bir yetkilendirme kriteri olarak, şimdi kullanıcının verilen rolde olup olmadığını kontrol eden isInRole()
yöntemini kullanacağız:
Bildiğiniz gibi, kullanıcının oturumu kapatması kimliğini silmemektedir. Bu nedenle, getIdentity()
yöntemi,
verilen tüm roller de dahil olmak üzere SimpleIdentity
nesnesini döndürmeye devam eder. Nette Framework „daha
az kod, daha fazla güvenlik“ ilkesine bağlıdır, bu nedenle rolleri kontrol ederken kullanıcının oturum açıp
açmadığını da kontrol etmeniz gerekmez. isInRole()
yöntemi etkili roller ile çalışır, yani
kullanıcı oturum açmışsa, kimliğe atanan roller kullanılır, oturum açmamışsa, bunun yerine otomatik bir özel rol
guest
kullanılır.
Yetkilendirici
Rollere ek olarak, kaynak ve operasyon terimlerini de tanıtacağız:
- rol** bir kullanıcı niteliğidir – örneğin moderatör, editör, ziyaretçi, kayıtlı kullanıcı, yönetici, …
- kaynak** uygulamanın mantıksal bir birimidir – makale, sayfa, kullanıcı, menü öğesi, anket, sunucu, …
- işlem** kullanıcının kaynak ile yapabileceği veya yapamayacağı belirli bir faaliyettir – görüntüleme, düzenleme, silme, oylama, …
Yetkilendirici, belirli bir rolün belirli bir kaynak ile belirli bir işlem gerçekleştirme iznine sahip
olup olmadığına karar veren bir nesnedir. Sadece bir yöntemle Nette\Security\Authorizator arayüzünü uygulayan
bir nesnedir isAllowed()
:
Yetkilendiriciyi DI konteynerinin bir servisi olarak yapılandırmaya ekliyoruz:
Ve aşağıda bir kullanım örneği verilmiştir. Bu kez yetkilendiricinin değil
Nette\Security\User::isAllowed()
yöntemini çağırdığımıza dikkat edin, bu nedenle ilk parametre
$role
değildir. Bu yöntem MyAuthorizator::isAllowed()
adresini tüm kullanıcı rolleri için sırayla
çağırır ve en az birinin izni varsa true değerini döndürür.
Her iki argüman da isteğe bağlıdır ve varsayılan değerleri her şey anlamına gelir.
İzin ACL
Nette, izin ve erişim kontrolü için hafif ve esnek bir ACL (Erişim Kontrol Listesi) katmanı sunan Nette\Security\Permission sınıfı olan yerleşik bir yetkilendirici uygulaması ile birlikte gelir. Bu sınıfla çalıştığımızda, roller, kaynaklar ve bireysel izinler tanımlarız. Ve roller ve kaynaklar hiyerarşiler oluşturabilir. Açıklamak için bir web uygulaması örneği göstereceğiz:
guest
: oturum açmamış, web'in herkese açık bölümünü okumasına ve taramasına izin verilen ziyaretçi, yani makaleleri okumak, yorum yapmak ve anketlerde oy kullanmakregistered
: oturum açmış kullanıcı, bunun üzerine yorum gönderebiliradmin
: makaleleri, yorumları ve anketleri yönetebilir
Bu nedenle, belirli roller tanımladık (guest
, registered
ve admin
) ve
kullanıcıların erişebileceği veya üzerinde işlem yapabileceği kaynakları (article
, comments
,
poll
) belirttik (view
, vote
, add
, edit
).
Permission sınıfının bir örneğini oluşturur ve rolleri tanımlarız. Rollerin kalıtımını kullanmak
mümkündür, bu da örneğin admin
rolüne sahip bir kullanıcının sıradan bir web sitesi ziyaretçisinin
yapabildiklerini (ve tabii ki daha fazlasını) yapabilmesini sağlar.
Şimdi kullanıcıların erişebileceği kaynakların bir listesini tanımlayacağız:
Kaynaklar kalıtım da kullanabilir, örneğin $acl->addResource('perex', 'article')
adresini
ekleyebiliriz.
Ve şimdi en önemli şey. Kimin ne yapabileceğini belirleyen kuralları aralarında tanımlayacağız:
Birinin bir kaynağa erişmesini engellemek istersek ne olur?
Şimdi kurallar setini oluşturduğumuzda, basitçe yetkilendirme sorgularını sorabiliriz:
Aynı şey kayıtlı bir kullanıcı için de geçerlidir, ancak o da yorum yapabilir:
Yönetici, anketler hariç her şeyi düzenleyebilir:
İzinler dinamik olarak da değerlendirilebilir ve kararı tüm parametrelerin aktarıldığı kendi geri çağrımıza bırakabiliriz:
Ancak, rollerin ve kaynakların adlarının yeterli olmadığı bir durumu nasıl çözebiliriz, yani örneğin, bir rolün
registered
bir kaynağı article
yalnızca yazarı ise düzenleyebileceğini tanımlamak istiyoruz?
Dizeler yerine nesneler kullanacağız, rol Nette\Security\Role nesnesi ve kaynak Nette\Security\Resource olacak. Metotları
getRoleId()
resp. getResourceId()
orijinal dizgileri döndürecektir:
Ve şimdi bir kural oluşturalım:
ACL, nesneler geçirilerek sorgulanır:
Bir rol, bir veya daha fazla başka rolden miras alabilir. Ancak, bir atanın belirli bir eyleme izin vermesi ve diğerinin bunu reddetmesi durumunda ne olur? O zaman rol ağırlığı devreye girer – miras alınacak roller dizisindeki son rol en büyük, ilk rol ise en düşük ağırlığa sahiptir:
Roller ve kaynaklar da kaldırılabilir (removeRole()
, removeResource()
), kurallar da geri
alınabilir (removeAllow()
, removeDeny()
). Tüm doğrudan üst rollerin dizisi
getRoleParents()
döndürür. İki varlığın birbirinden miras alıp almadığı roleInheritsFrom()
ve
resourceInheritsFrom()
döndürür.
Hizmet Olarak Ekle
Oluşturduğumuz ACL'yi $user
nesnesi tarafından kullanılabilmesi için yani örneğin
$user->isAllowed('article', 'view')
kodunda kullanabilmemiz için yapılandırmaya bir servis olarak eklememiz
gerekiyor. Bu amaçla bunun için bir fabrika yazacağız:
Ve bunu yapılandırmaya ekleyeceğiz:
Sunucularda, örneğin startup()
yönteminde izinleri doğrulayabilirsiniz: