Πώς να χρησιμοποιήσετε το #[Requires] Attribute

Κατά τη συγγραφή μιας εφαρμογής ιστού, συναντάτε συχνά την ανάγκη να περιορίσετε την πρόσβαση σε ορισμένα τμήματα της εφαρμογής σας. Ίσως θέλετε κάποια αιτήματα να μπορούν να στέλνουν δεδομένα μόνο μέσω μιας φόρμας (χρησιμοποιώντας έτσι τη μέθοδο POST) ή να είναι προσβάσιμα μόνο σε κλήσεις AJAX. Στο Nette Framework 3.2, έχει εισαχθεί ένα νέο εργαλείο που σας επιτρέπει να ορίσετε τέτοιους περιορισμούς με κομψότητα και σαφήνεια: το #[Requires] χαρακτηριστικό.

Το χαρακτηριστικό είναι ένας ειδικός δείκτης στην PHP, τον οποίο προσθέτετε πριν από τον ορισμό μιας κλάσης ή μεθόδου. Εφόσον πρόκειται ουσιαστικά για μια κλάση, πρέπει να συμπεριλάβετε τη ρήτρα use για να λειτουργήσουν τα παρακάτω παραδείγματα:

use Nette\Application\Attributes\Requires;

Μπορείτε να χρησιμοποιήσετε το #[Requires] με την ίδια την κλάση presenter και σε αυτές τις μεθόδους:

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

Οι δύο τελευταίες μέθοδοι αφορούν επίσης συστατικά, οπότε μπορείτε να χρησιμοποιήσετε το χαρακτηριστικό και με αυτά.

Εάν δεν πληρούνται οι συνθήκες που καθορίζονται από το χαρακτηριστικό, ενεργοποιείται ένα σφάλμα HTTP 4xx.

Μέθοδοι HTTP

Μπορείτε να καθορίσετε ποιες μέθοδοι HTTP (όπως GET, POST κ.λπ.) επιτρέπονται για πρόσβαση. Για παράδειγμα, αν θέλετε να επιτρέψετε την πρόσβαση μόνο με την υποβολή μιας φόρμας, ορίστε:

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

Γιατί πρέπει να χρησιμοποιείτε POST αντί για GET για ενέργειες αλλαγής κατάστασης και πώς να το κάνετε; Διαβάστε τον οδηγό.

Μπορείτε να καθορίσετε μια μέθοδο ή έναν πίνακα μεθόδων. Μια ειδική περίπτωση είναι η τιμή '*' για την ενεργοποίηση όλων των μεθόδων, την οποία οι παρουσιαστές δεν επιτρέπουν από προεπιλογή για λόγους ασφαλείας.

Κλήσεις AJAX

Αν θέλετε ένας παρουσιαστής ή μια μέθοδος να είναι προσβάσιμη μόνο για αιτήσεις AJAX, χρησιμοποιήστε:

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

Ίδια προέλευση

Για να ενισχύσετε την ασφάλεια, μπορείτε να απαιτήσετε η αίτηση να γίνεται από τον ίδιο τομέα. Αυτό αποτρέπει την ευπάθεια σε CSRF:

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

Για το handle<Signal>() μεθόδους, απαιτείται αυτόματα πρόσβαση από τον ίδιο τομέα. Έτσι, αν θέλετε να επιτρέψετε την πρόσβαση από οποιονδήποτε τομέα, καθορίστε:

#[Requires(sameOrigin: false)]
public function handleList(): void
{
}

Πρόσβαση μέσω Forward

Μερικές φορές είναι χρήσιμο να περιορίσετε την πρόσβαση σε έναν παρουσιαστή, ώστε να είναι διαθέσιμος μόνο έμμεσα, για παράδειγμα, χρησιμοποιώντας τις μεθόδους forward() ή switch() από έναν άλλο παρουσιαστή. Με αυτόν τον τρόπο προστατεύονται οι παρουσιαστές σφαλμάτων, ώστε να μην μπορούν να ενεργοποιηθούν από μια διεύθυνση URL:

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

Στην πράξη, είναι συχνά απαραίτητο να επισημαίνονται ορισμένες προβολές στις οποίες μπορεί να γίνει πρόσβαση μόνο με βάση τη λογική του παρουσιαστή. Και πάλι, έτσι ώστε να μην μπορούν να ανοιχτούν απευθείας:

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
	{
	}
}

Ειδικές δράσεις

Μπορείτε επίσης να περιορίσετε ότι ορισμένος κώδικας, όπως η δημιουργία ενός στοιχείου, θα είναι προσβάσιμος μόνο για συγκεκριμένες ενέργειες στον παρουσιαστή:

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

Για μια μεμονωμένη ενέργεια, δεν χρειάζεται να γράψετε έναν πίνακα: #[Requires(actions: 'default')]

Προσαρμοσμένα χαρακτηριστικά

Αν θέλετε να χρησιμοποιήσετε το #[Requires] χαρακτηριστικό επανειλημμένα με τις ίδιες ρυθμίσεις, μπορείτε να δημιουργήσετε το δικό σας χαρακτηριστικό που θα κληρονομεί #[Requires] και να το ορίσετε σύμφωνα με τις ανάγκες σας.

Για παράδειγμα, #[SingleAction] επιτρέπει την πρόσβαση μόνο μέσω της ενέργειας default:

#[Attribute]
class SingleAction extends Nette\Application\Attributes\Requires
{
	public function __construct()
	{
		parent::__construct(actions: 'default');
	}
}

#[SingleAction]
class SingleActionPresenter extends Nette\Application\UI\Presenter
{
}

Ή #[RestMethods] θα επιτρέψει την πρόσβαση μέσω όλων των μεθόδων HTTP που χρησιμοποιούνται για το REST API:

#[\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
{
}

Συμπέρασμα

Το #[Requires] σας δίνει μεγάλη ευελιξία και έλεγχο στον τρόπο πρόσβασης στις ιστοσελίδες σας. Χρησιμοποιώντας απλούς, αλλά ισχυρούς κανόνες, μπορείτε να ενισχύσετε την ασφάλεια και την ορθή λειτουργία της εφαρμογής σας. Όπως μπορείτε να δείτε, η χρήση χαρακτηριστικών στη Nette μπορεί όχι μόνο να απλοποιήσει την εργασία σας αλλά και να την ασφαλίσει.