Sessions
Το HTTP είναι ένα πρωτόκολλο χωρίς κατάσταση, αλλά σχεδόν κάθε εφαρμογή χρειάζεται να διατηρεί την κατάσταση μεταξύ των αιτημάτων, για παράδειγμα, το περιεχόμενο ενός καλαθιού αγορών. Αυτός είναι ακριβώς ο σκοπός των sessions. Θα δείξουμε:
- πώς να χρησιμοποιείτε τα sessions
- πώς να αποφύγετε τις συγκρούσεις ονομάτων
- πώς να ορίσετε τη λήξη
Όταν χρησιμοποιείτε sessions, κάθε χρήστης λαμβάνει ένα μοναδικό αναγνωριστικό που ονομάζεται session ID, το οποίο μεταδίδεται σε ένα cookie. Αυτό χρησιμεύει ως κλειδί για τα δεδομένα του session. Σε αντίθεση με τα cookies, τα οποία αποθηκεύονται στην πλευρά του προγράμματος περιήγησης, τα δεδομένα του session αποθηκεύονται στην πλευρά του διακομιστή.
Ρυθμίζουμε το session στην διαμόρφωση, η επιλογή του χρόνου λήξης είναι ιδιαίτερα σημαντική.
Η διαχείριση του session γίνεται από το αντικείμενο Nette\Http\Session, στο οποίο μπορείτε να
αποκτήσετε πρόσβαση ζητώντας το μέσω έγχυσης εξάρτησης. Στους
presenters, απλά καλέστε $session = $this->getSession()
.
Έναρξη Session
Από προεπιλογή, το Nette ξεκινά αυτόματα το session τη στιγμή που αρχίζουμε
να διαβάζουμε ή να γράφουμε δεδομένα σε αυτό. Μπορείτε να ξεκινήσετε το
session χειροκίνητα χρησιμοποιώντας το $session->start()
.
Όταν ξεκινά ένα session, η PHP στέλνει κεφαλίδες HTTP που επηρεάζουν την προσωρινή αποθήκευση, δείτε session_cache_limiter, και ενδεχομένως ένα cookie με το session ID. Επομένως, είναι απαραίτητο να ξεκινάτε πάντα το session πριν στείλετε οποιαδήποτε έξοδο στο πρόγραμμα περιήγησης, διαφορετικά θα προκληθεί εξαίρεση. Εάν γνωρίζετε ότι το session θα χρησιμοποιηθεί κατά την απόδοση της σελίδας, ξεκινήστε το χειροκίνητα εκ των προτέρων, για παράδειγμα, στον presenter.
Στη λειτουργία ανάπτυξης, το Tracy ξεκινά το session επειδή το χρησιμοποιεί για την εμφάνιση των γραμμών με ανακατευθύνσεις και αιτήματα AJAX στο Tracy Bar.
Ενότητες
Στην καθαρή PHP, ο χώρος αποθήκευσης δεδομένων του session υλοποιείται ως
ένας πίνακας προσβάσιμος μέσω της καθολικής μεταβλητής $_SESSION
.
Το πρόβλημα είναι ότι οι εφαρμογές συνήθως αποτελούνται από έναν
αριθμό ανεξάρτητων τμημάτων, και εάν όλα έχουν πρόσβαση μόνο σε έναν
πίνακα, αργά ή γρήγορα θα προκύψει σύγκρουση ονομάτων.
Το Nette Framework λύνει αυτό το πρόβλημα διαιρώντας ολόκληρο τον χώρο σε ενότητες (αντικείμενα Nette\Http\SessionSection). Κάθε μονάδα χρησιμοποιεί τότε τη δική της ενότητα με ένα μοναδικό όνομα, και δεν μπορεί να προκύψει σύγκρουση.
Λαμβάνουμε μια ενότητα από το session:
$section = $session->getSection('μοναδικό όνομα');
Στον presenter, απλά χρησιμοποιήστε το getSession()
με μια παράμετρο:
// $this είναι ένας Presenter
$section = $this->getSession('μοναδικό όνομα');
Η ύπαρξη μιας ενότητας μπορεί να ελεγχθεί με τη μέθοδο
$session->hasSection('μοναδικό όνομα')
.
Η εργασία με την ίδια την ενότητα είναι τότε πολύ εύκολη
χρησιμοποιώντας τις μεθόδους set()
, get()
και remove()
:
// εγγραφή μεταβλητής
$section->set('userName', 'franta');
// ανάγνωση μεταβλητής, επιστρέφει null εάν δεν υπάρχει
echo $section->get('userName');
// διαγραφή μεταβλητής
$section->remove('userName');
Για να λάβετε όλες τις μεταβλητές από την ενότητα, μπορείτε να
χρησιμοποιήσετε έναν βρόχο foreach
:
foreach ($section as $key => $val) {
echo "$key = $val";
}
Ρύθμιση Λήξης
Είναι δυνατό να οριστεί η λήξη για μεμονωμένες ενότητες ή ακόμη και για μεμονωμένες μεταβλητές. Μπορούμε να αφήσουμε τη σύνδεση του χρήστη να λήξει σε 20 λεπτά, αλλά ταυτόχρονα να θυμόμαστε το περιεχόμενο του καλαθιού αγορών.
// η ενότητα λήγει μετά από 20 λεπτά
$section->setExpiration('20 minutes');
Για να ορίσετε τη λήξη μεμονωμένων μεταβλητών, χρησιμοποιήστε την
τρίτη παράμετρο της μεθόδου set()
:
// η μεταβλητή 'flash' λήγει μετά από 30 δευτερόλεπτα
$section->set('flash', $message, '30 seconds');
Μην ξεχνάτε ότι ο χρόνος λήξης ολόκληρου του session (δείτε διαμόρφωση session) πρέπει να είναι ίσος ή μεγαλύτερος από τον χρόνο που ορίζεται για μεμονωμένες ενότητες ή μεταβλητές.
Η ακύρωση μιας προηγουμένως ορισμένης λήξης επιτυγχάνεται με τη
μέθοδο removeExpiration()
. Η άμεση ακύρωση ολόκληρης της ενότητας
διασφαλίζεται από τη μέθοδο remove()
.
Συμβάντα $onStart, $onBeforeWrite
Το αντικείμενο Nette\Http\Session
έχει συμβάντα $onStart
και $onBeforeWrite
,
οπότε μπορείτε να προσθέσετε επανακλήσεις που καλούνται μετά την
έναρξη του session ή πριν από την εγγραφή του στον δίσκο και τον επακόλουθο
τερματισμό του.
$session->onBeforeWrite[] = function () {
// γράφουμε δεδομένα στο session
$this->section->set('basket', $this->basket);
};
Διαχείριση Session
Επισκόπηση των μεθόδων της κλάσης Nette\Http\Session
για τη διαχείριση
του session:
start(): void
Ξεκινά το session.
isStarted(): bool
Έχει ξεκινήσει το session;
close(): void
Τερματίζει το session. Το session τερματίζεται αυτόματα στο τέλος της εκτέλεσης του σεναρίου.
destroy(): void
Τερματίζει και διαγράφει το session.
exists(): bool
Περιέχει το αίτημα HTTP ένα cookie με το session ID;
regenerateId(): void
Δημιουργεί ένα νέο τυχαίο session ID. Τα δεδομένα διατηρούνται.
getId(): string
Επιστρέφει το session ID.
Διαμόρφωση
Ρυθμίζουμε το session στην διαμόρφωση. Εάν γράφετε μια εφαρμογή που δεν χρησιμοποιεί DI container, αυτές οι μέθοδοι χρησιμοποιούνται για τη διαμόρφωση. Πρέπει να κληθούν πριν από την έναρξη του session.
setName (string $name): static
Ορίζει το όνομα του cookie στο οποίο μεταδίδεται το session ID. Το
προεπιλεγμένο όνομα είναι PHPSESSID
. Είναι χρήσιμο εάν εκτελείτε
πολλές διαφορετικές εφαρμογές στον ίδιο ιστότοπο.
getName(): string
Επιστρέφει το όνομα του cookie στο οποίο μεταδίδεται το session ID.
setOptions (array $options): static
Διαμορφώνει το session. Μπορείτε να ορίσετε όλες τις PHP οδηγίες session (σε μορφή camelCase, π.χ.
αντί για session.save_path
γράφουμε savePath
) καθώς και το readAndClose.
setExpiration (?string $time): static
Ορίζει τον χρόνο αδράνειας μετά τον οποίο λήγει το session.
setCookieParameters (string $path, ?string $domain=null, ?bool $secure=null, ?string $samesite=null): static
Ρύθμιση παραμέτρων για το cookie. Μπορείτε να αλλάξετε τις προεπιλεγμένες τιμές των παραμέτρων στην διαμόρφωση.
setSavePath (string $path): static
Ορίζει τον κατάλογο όπου αποθηκεύονται τα αρχεία session.
setHandler (\SessionHandlerInterface $handler): static
Ορίζει έναν προσαρμοσμένο χειριστή, δείτε την τεκμηρίωση της PHP.
Ασφάλεια Πρώτα
Ο διακομιστής υποθέτει ότι επικοινωνεί πάντα με τον ίδιο χρήστη, εφόσον τα αιτήματα συνοδεύονται από το ίδιο session ID. Ο ρόλος των μηχανισμών ασφαλείας είναι να διασφαλίσουν ότι αυτό συμβαίνει πραγματικά και ότι δεν είναι δυνατό να κλαπεί ή να πλαστογραφηθεί το αναγνωριστικό.
Επομένως, το Nette Framework διαμορφώνει σωστά τις οδηγίες PHP έτσι ώστε το session ID να μεταδίδεται μόνο σε cookies, να το καθιστά μη προσβάσιμο από JavaScript και να αγνοεί τυχόν αναγνωριστικά στο URL. Επιπλέον, σε κρίσιμες στιγμές, όπως η σύνδεση του χρήστη, δημιουργεί ένα νέο session ID.
Η συνάρτηση ini_set χρησιμοποιείται για τη διαμόρφωση της PHP, την οποία δυστυχώς ορισμένοι πάροχοι φιλοξενίας απαγορεύουν. Εάν αυτό συμβαίνει και με τον δικό σας πάροχο, προσπαθήστε να διαπραγματευτείτε μαζί του για να σας επιτρέψει τη συνάρτηση ή τουλάχιστον να διαμορφώσει τον διακομιστή.