#[Requires] Attribute'u Nasıl Kullanılır
Bir web uygulaması yazarken, uygulamanızın belirli bölümlerine erişimi kısıtlama ihtiyacıyla sık
karşılaşırsınız. Belki bazı isteklerin yalnızca bir form üzerinden veri gönderebilmesini (yani POST metodunu
kullanmasını) ya da yalnızca AJAX çağrılarına açık olmasını istersiniz. Nette Framework 3.2'de, bu tür
kısıtlamaları şık ve anlaşılır biçimde koymanızı sağlayan yeni bir araç geldi: #[Requires]
attribute'u.
Attribute, PHP'de bir sınıf ya da metot tanımından önce eklediğiniz özel bir işarettir. Özünde bir sınıf
olduğundan, aşağıdaki örneklerin çalışması için use deyimini eklemeniz gerekir:
use Nette\Application\Attributes\Requires;
#[Requires] attribute'unu presenter sınıfının kendisinde ve şu metotlarda kullanabilirsiniz:
action<Action>()render<View>()handle<Signal>()createComponent<Name>()
Son iki metot bileşenler için de geçerlidir, dolayısıyla attribute'u onlarla da kullanabilirsiniz.
Attribute'un belirttiği koşullar sağlanmazsa bir HTTP 4xx hatası tetiklenir.
HTTP Metotları
Erişim için hangi HTTP metotlarına (GET, POST vb.) izin verildiğini belirtebilirsiniz. Örneğin erişime yalnızca bir form gönderilerek izin vermek istiyorsanız şunu ayarlayın:
class AdminPresenter extends Nette\Application\UI\Presenter
{
#[Requires(methods: 'POST')]
public function actionDelete(int $id): void
{
}
}
Durum değiştiren eylemlerde neden GET yerine POST kullanmalısınız ve bunu nasıl yaparsınız? Kılavuzu okuyun.
Bir metot ya da metot dizisi belirtebilirsiniz. Özel bir durum, tüm metotlara izin veren '*' değeridir;
presenter'lar bunu güvenlik nedeniyle
varsayılan olarak yapmaz.
AJAX Çağrıları
Bir presenter'ın ya da metodun yalnızca AJAX istekleriyle erişilebilir olmasını istiyorsanız şunu kullanın:
#[Requires(ajax: true)]
class AjaxPresenter extends Nette\Application\UI\Presenter
{
}
Aynı Kaynak
Güvenliği artırmak için isteğin aynı alan adından yapılmasını zorunlu kılabilirsiniz. Bu, CSRF açığını önler:
#[Requires(sameOrigin: true)]
class SecurePresenter extends Nette\Application\UI\Presenter
{
}
handle<Signal>() metotlarında aynı alan adından erişim otomatik olarak zorunludur. Bu yüzden herhangi
bir alan adından erişime izin vermek istiyorsanız şunu belirtin:
#[Requires(sameOrigin: false)]
public function handleList(): void
{
}
Forward ile Erişim
Bazen bir presenter'a erişimi, yalnızca dolaylı olarak, örneğin başka bir presenter'dan forward() ya da
switch() metotlarıyla ulaşılabilecek şekilde kısıtlamak yararlıdır. Örneğin hata presenter'ları, URL'den
tetiklenmelerini önlemek için böyle korunur:
#[Requires(forward: true)]
class ForwardedPresenter extends Nette\Application\UI\Presenter
{
}
Pratikte, yalnızca presenter'daki mantığa göre erişilebilecek belirli view'ları işaretlemek çoğu zaman gerekir. Yine, doğrudan açılamamaları için:
class ProductPresenter extends Nette\Application\UI\Presenter
{
public function actionDefault(int $id): void
{
$product = $this->facade->getProduct($id);
if (!$product) {
$this->setView('notfound');
}
}
#[Requires(forward: true)]
public function renderNotFound(): void
{
}
}
Belirli Eylemler
Bileşen oluşturmak gibi belirli bir kodun yalnızca presenter'daki belirli eylemlerde erişilebilir olmasını da kısıtlayabilirsiniz:
class EditDeletePresenter extends Nette\Application\UI\Presenter
{
#[Requires(actions: ['add', 'edit'])]
public function createComponentPostForm()
{
}
}
Tek bir eylem söz konusuysa dizi yazmaya gerek yoktur: #[Requires(actions: 'default')]
Özel Attribute'lar
#[Requires] attribute'unu aynı ayarlarla defalarca kullanmak istiyorsanız, #[Requires]
attribute'undan türeyen ve onu ihtiyacınıza göre yapılandıran kendi attribute'unuzu oluşturabilirsiniz.
Örneğin #[SingleAction], erişime yalnızca default eylemi üzerinden izin verir:
#[\Attribute]
class SingleAction extends Nette\Application\Attributes\Requires
{
public function __construct()
{
parent::__construct(actions: 'default');
}
}
#[SingleAction]
class SingleActionPresenter extends Nette\Application\UI\Presenter
{
}
Ya da #[RestMethods], REST API'de kullanılan tüm HTTP metotlarıyla erişime izin verir:
#[\Attribute]
class RestMethods extends Nette\Application\Attributes\Requires
{
public function __construct()
{
parent::__construct(methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE']);
}
}
#[RestMethods]
class ApiPresenter extends Nette\Application\UI\Presenter
{
}
Sonuç
#[Requires] attribute'u, web sayfalarınıza nasıl erişildiği konusunda size büyük esneklik ve denetim verir.
Basit ama güçlü kurallarla uygulamanızın güvenliğini ve düzgün çalışmasını artırabilirsiniz. Gördüğünüz gibi,
Nette'de attribute kullanmak işinizi yalnızca kolaylaştırmakla kalmaz, aynı zamanda güvenli hâle getirir.