Πώς να χρησιμοποιήσετε το attribute
#[Requires]
Όταν γράφετε μια διαδικτυακή εφαρμογή, συχνά αντιμετωπίζετε
την ανάγκη να περιορίσετε την πρόσβαση σε ορισμένα τμήματα της
εφαρμογής σας. Ίσως θέλετε ορισμένα αιτήματα να μπορούν να στέλνουν
δεδομένα μόνο μέσω φόρμας (δηλαδή με τη μέθοδο POST), ή να είναι
προσβάσιμα μόνο για κλήσεις AJAX. Στο Nette Framework 3.2, εμφανίστηκε ένα νέο
εργαλείο που σας επιτρέπει να ορίσετε τέτοιους περιορισμούς με πολύ
κομψό και σαφή τρόπο: το attribute #[Requires]
.
Το attribute είναι μια ειδική ετικέτα στην PHP, την οποία προσθέτετε πριν από τον ορισμό μιας κλάσης ή μεθόδου. Επειδή είναι στην πραγματικότητα μια κλάση, για να λειτουργήσουν τα παρακάτω παραδείγματα, είναι απαραίτητο να συμπεριλάβετε τη δήλωση use:
use Nette\Application\Attributes\Requires;
Μπορείτε να χρησιμοποιήσετε το attribute #[Requires]
στην ίδια την
κλάση του presenter και επίσης σε αυτές τις μεθόδους:
action<Action>()
render<View>()
handle<Signal>()
createComponent<Name>()
Οι δύο τελευταίες μέθοδοι αφορούν επίσης τα components, οπότε μπορείτε να χρησιμοποιήσετε το attribute και σε αυτά.
Αν δεν πληρούνται οι προϋποθέσεις που αναφέρει το attribute, προκαλείται σφάλμα HTTP 4xx.
Μέθοδοι HTTP
Μπορείτε να καθορίσετε ποιες μέθοδοι HTTP (όπως GET, POST κ.λπ.) επιτρέπονται για πρόσβαση. Για παράδειγμα, αν θέλετε να επιτρέψετε την πρόσβαση μόνο με την υποβολή φόρμας, ορίζετε:
class AdminPresenter extends Nette\Application\UI\Presenter
{
#[Requires(methods: 'POST')]
public function actionDelete(int $id): void
{
}
}
Γιατί πρέπει να χρησιμοποιείτε POST αντί για GET για ενέργειες που αλλάζουν την κατάσταση και πώς να το κάνετε; Διαβάστε τον οδηγό.
Μπορείτε να καθορίσετε μια μέθοδο ή έναν πίνακα μεθόδων. Μια ειδική
περίπτωση είναι η τιμή '*'
, η οποία επιτρέπει όλες τις μεθόδους,
κάτι που οι presenters κανονικά δεν επιτρέπουν για λόγους
ασφαλείας.
Κλήσεις AJAX
Αν θέλετε ο presenter ή η μέθοδος να είναι διαθέσιμη μόνο για αιτήσεις 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
Μερικές φορές είναι χρήσιμο να περιορίσετε την πρόσβαση στον presenter
έτσι ώστε να είναι διαθέσιμος μόνο έμμεσα, για παράδειγμα,
χρησιμοποιώντας τη μέθοδο forward()
ή switch()
από άλλο presenter.
Έτσι προστατεύονται, για παράδειγμα, οι error-presenters, ώστε να μην είναι
δυνατό να κληθούν από το URL:
#[Requires(forward: true)]
class ForwardedPresenter extends Nette\Application\UI\Presenter
{
}
Στην πράξη, συχνά είναι απαραίτητο να επισημάνετε ορισμένα views, στα οποία μπορείτε να φτάσετε μόνο βάσει της λογικής στον 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
{
}
}
Συγκεκριμένες ενέργειες
Μπορείτε επίσης να περιορίσετε ότι ένας συγκεκριμένος κώδικας, όπως η δημιουργία ενός component, θα είναι διαθέσιμος μόνο για συγκεκριμένες actions στον presenter:
class EditDeletePresenter extends Nette\Application\UI\Presenter
{
#[Requires(actions: ['add', 'edit'])]
public function createComponentPostForm()
{
}
}
Σε περίπτωση μίας action, δεν χρειάζεται να γράψετε
πίνακα: #[Requires(actions: 'default')]
Προσαρμοσμένα attributes
Αν θέλετε να χρησιμοποιήσετε το attribute #[Requires]
επανειλημμένα με
τις ίδιες ρυθμίσεις, μπορείτε να δημιουργήσετε το δικό σας attribute που θα
κληρονομεί το #[Requires]
και θα το ρυθμίζει ανάλογα με τις
ανάγκες.
Για παράδειγμα, το #[SingleAction]
θα επιτρέπει την πρόσβαση μόνο
μέσω της action 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
{
}
Συμπέρασμα
Το attribute #[Requires]
σας δίνει μεγάλη ευελιξία και έλεγχο στο πώς
είναι προσβάσιμες οι ιστοσελίδες σας. Χρησιμοποιώντας απλούς αλλά
ισχυρούς κανόνες, μπορείτε να αυξήσετε την ασφάλεια και τη σωστή
λειτουργία της εφαρμογής σας. Όπως βλέπετε, η χρήση attributes στο Nette μπορεί
όχι μόνο να διευκολύνει τη δουλειά σας, αλλά και να την ασφαλίσει.