#[Requires] Niteliği 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 sık karşılaşırsınız. Belki bazı isteklerin yalnızca bir form kullanarak (yani POST metoduyla) veri gönderebilmesini veya yalnızca AJAX çağrıları için erişilebilir olmasını istersiniz. Nette Framework 3.2'de, bu tür kısıtlamaları çok zarif ve anlaşılır bir şekilde ayarlamanıza olanak tanıyan yeni bir araç ortaya çıktı: #[Requires] niteliği.

Nitelik, bir sınıf veya metot tanımının önüne eklediğiniz PHP'deki özel bir işarettir. Aslında bir sınıf olduğu için, aşağıdaki örneklerin çalışması için use ifadesini belirtmek gerekir:

use Nette\Application\Attributes\Requires;

#[Requires] niteliğini presenter sınıfının kendisinde ve ayrıca şu metotlarda kullanabilirsiniz:

  • action<Action>()
  • render<View>()
  • handle<Signal>()
  • createComponent<Name>()

Son iki metot bileşenlerle de ilgilidir, yani niteliği onlarda da kullanabilirsiniz.

Niteliğin belirttiği koşullar karşılanmazsa, bir HTTP 4xx hatası tetiklenir.

HTTP Metotları

Erişim için hangi HTTP metotlarının (GET, POST vb. gibi) izinli olduğunu belirleyebilirsiniz. Örneğin, yalnızca bir form göndererek erişime izin vermek istiyorsanız, şunu ayarlarsınız:

class AdminPresenter extends Nette\Application\UI\Presenter
{
	#[Requires(methods: 'POST')]
	public function actionDelete(int $id): void
	{
	}
}

Durumu değiştiren eylemler için neden GET yerine POST kullanmalısınız ve bunu nasıl yapmalısınız? Kılavuzu okuyun.

Bir metot veya metot dizisi belirtebilirsiniz. Özel bir durum, tüm metotlara izin veren '*' değeridir, ki bu presenter'ların standart olarak güvenlik nedenleriyle izin vermediği bir durumdur.

AJAX Çağrıları

Bir presenter veya metodun yalnızca AJAX istekleri için kullanılabilir 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 güvenlik 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 zorunlu kılınır. Dolayısıyla tam tersine, 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() veya switch() metodunu kullanarak kullanılabilir olacak şekilde kısıtlamak yararlıdır. Örneğin error-presenter'lar bu şekilde korunur, böylece URL'den çağrılamazlar:

#[Requires(forward: true)]
class ForwardedPresenter extends Nette\Application\UI\Presenter
{
}

Pratikte, presenter'daki mantığa dayalı olarak erişilebilen belirli view'leri işaretlemek genellikle gereklidir. Yani 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

Ayrıca, belirli bir kodun, örneğin bir bileşenin oluşturulmasının, yalnızca presenter'daki belirli eylemler için kullanılabilir olmasını da kısıtlayabilirsiniz:

class EditDeletePresenter extends Nette\Application\UI\Presenter
{
	#[Requires(actions: ['add', 'edit'])]
	public function createComponentPostForm()
	{
	}
}

Tek bir eylem durumunda, bir dizi yazmaya gerek yoktur: #[Requires(actions: 'default')]

Özel Nitelikler

#[Requires] niteliğini aynı ayarlarla tekrar tekrar kullanmak istiyorsanız, #[Requires]'ı miras alan ve onu ihtiyaçlara göre ayarlayan kendi niteliğinizi oluşturabilirsiniz.

Örneğin, #[SingleAction] yalnızca default eylemi aracılığıyla erişime 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
{
}

Veya #[RestMethods], REST API için kullanılan tüm HTTP metotları aracılığı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] niteliği, web sayfalarınızın nasıl erişilebilir olduğu konusunda size büyük esneklik ve kontrol sağlar. Basit ama güçlü kurallar kullanarak uygulamanızın güvenliğini ve doğru çalışmasını artırabilirsiniz. Gördüğünüz gibi, Nette'de nitelikleri kullanmak işinizi yalnızca kolaylaştırmakla kalmaz, aynı zamanda güvence altına da alabilir.