Όταν συνδέεστε σε μια σύγχρονη εφαρμογή μιας σελίδας (όπως το React ή το Vue) ή μια εφαρμογή για κινητά, ο διακομιστής χρειάζεται έναν τρόπο να θυμάται ποιος είστε. Παραδοσιακά, το έκανε αυτό αποθηκεύοντας ένα "αναγνωριστικό περιόδου σύνδεσης" σε μια τεράστια βάση δεδομένων στον διακομιστή και ρίχνοντας ένα cookie στο πρόγραμμα περιήγησής σας. Κάθε φορά που κάνατε κλικ σε ένα κουμπί, ο διακομιστής έπρεπε να αναζητήσει αυτό το αναγνωριστικό στη βάση δεδομένων του. Αυτό ονομάζεται έλεγχος ταυτότητας κατάστασης.
Ωστόσο, στην εποχή των μικροϋπηρεσιών και της κλίμακας cloud, οι βάσεις δεδομένων έγιναν εμπόδιο. Για να το λύσουν αυτό, οι προγραμματιστές υιοθέτησαν Έλεγχος ταυτότητας χωρίς πολιτεία μέσω JSON Web Tokens (JWT). Με το JWT, ο διακομιστής δεν χρειάζεται να θυμάται ποιος είστε—το πρόγραμμα περιήγησής σας λέει στον διακομιστή ακριβώς ποιος είστε και χρησιμοποιεί κρυπτογραφία για να το αποδείξει.
Η ανατομία ενός JWT
Εάν επιθεωρήσετε την κυκλοφορία δικτύου αφού συνδεθείτε σε μια σύγχρονη εφαρμογή, πιθανότατα θα δείτε μια κεφαλίδα "Authorization: Bearer" ακολουθούμενη από μια μεγάλη, τυχαίας εμφάνισης σειρά χαρακτήρων που χωρίζονται με δύο τελείες. Αυτό είναι ένα JWT.
Ένα JWT αποτελείται από τρία ακριβώς μέρη: Header.Payload.Signature.
1. Η Κεφαλίδα
Το πρώτο μέρος είναι ένα αντικείμενο JSON με κωδικοποίηση Base64URL που απλώς περιγράφει το διακριτικό. Συνήθως περιέχει δύο ιδιότητες: τον τύπο του διακριτικού (JWT) και τον αλγόριθμο υπογραφής που χρησιμοποιείται (όπως το HMAC SHA256 ή το RSA).
2. Το ωφέλιμο φορτίο (αξιώσεις)
Το μεσαίο τμήμα είναι επίσης ένα αντικείμενο JSON με κωδικοποίηση Base64URL. Εδώ ζουν τα πραγματικά δεδομένα. Αυτά τα στοιχεία ονομάζονται "αξιώσεις". Για παράδειγμα, μπορεί να περιέχει το User ID σας, τον ρόλο σας (π.χ. "Διαχειριστής") και μια χρονική σήμανση λήξης. Επειδή αυτό το ωφέλιμο φορτίο συνδέεται με κάθε αίτημα, ο διακομιστής γνωρίζει αμέσως ποιος είστε χωρίς να ρωτήσει μια βάση δεδομένων.
ΚΡΙΣΙΜΗ ΠΡΟΕΙΔΟΠΟΙΗΣΗ: Το ωφέλιμο φορτίο είναι απλώς κωδικοποιημένο, όχι κρυπτογραφημένο. Όποιος παρακολουθεί ένα JWT μπορεί εύκολα να το αποκωδικοποιήσει και να διαβάσει το ωφέλιμο φορτίο. Μην αποθηκεύετε ποτέ κωδικούς πρόσβασης, αριθμούς κοινωνικής ασφάλισης ή ευαίσθητα δεδομένα μέσα σε ωφέλιμο φορτίο JWT.
3. Η Υπογραφή
Εάν κάποιος μπορεί να διαβάσει και να επεξεργαστεί το ωφέλιμο φορτίο, τι εμποδίζει έναν κακόβουλο χρήστη να αλλάξει τον ρόλο του από "Χρήστης" σε "Διαχειριστής"; Η απάντηση είναι η Υπογραφή.
Για να δημιουργήσει την υπογραφή, ο διακομιστής παίρνει την κεφαλίδα, το ωφέλιμο φορτίο και ένα εξαιρετικά ασφαλές Μυστικό κλειδί (γνωστό μόνο στον διακομιστή) και τα εκτελεί μέσω ενός κρυπτογραφικού αλγόριθμου (όπως ο SHA256). Ο κατακερματισμός που προκύπτει γίνεται η υπογραφή.
Όταν ο διακομιστής λαμβάνει ένα διακριτικό πίσω από τον πελάτη, υπολογίζει εκ νέου την υπογραφή χρησιμοποιώντας το μυστικό κλειδί του. Εάν ο χρήστης παραποιήσει το ωφέλιμο φορτίο (ακόμα και αλλάζοντας ένα μόνο γράμμα), η υπογραφή που υπολογίστηκε εκ νέου δεν θα ταιριάζει με την υπογραφή στο διακριτικό και ο διακομιστής θα απορρίψει αμέσως το αίτημα ως δόλιο.
Επιθεωρήστε τα Tokens με ασφάλεια
Χρειάζεστε να διαβάσετε το ωφέλιμο φορτίο ενός JWT για τον εντοπισμό σφαλμάτων της εφαρμογής σας; Χρησιμοποιήστε τον αποκωδικοποιητή JWT εκτός σύνδεσης για να επιθεωρήσετε άμεσα τις αξιώσεις χωρίς να στείλετε το ευαίσθητο διακριτικό σας σε έναν απομακρυσμένο διακομιστή.
Ανοίξτε τον αποκωδικοποιητή JWTΓιατί οι Microservices αγαπούν τα JWT
Φανταστείτε μια εταιρεία όπως το Netflix. Διαθέτουν διακομιστή ελέγχου ταυτότητας, διακομιστή ροής βίντεο και διακομιστή χρέωσης. Εάν χρησιμοποιούσαν παραδοσιακές περιόδους σύνδεσης, κάθε διακομιστής θα έπρεπε να επικοινωνεί συνεχώς με μια κεντρική βάση δεδομένων για να ελέγξει εάν ένας χρήστης είναι συνδεδεμένος.
Με τα JWT, ο διακομιστής ελέγχου ταυτότητας υπογράφει το διακριτικό χρησιμοποιώντας ένα ιδιωτικό κλειδί. Στη συνέχεια, ο χρήστης μεταβιβάζει αυτό το διακριτικό απευθείας στον διακομιστή βίντεο. Επειδή ο διακομιστής βίντεο έχει το δημόσιο κλειδί, μπορεί να επαληθεύσει ανεξάρτητα την υπογραφή. Ο διακομιστής βίντεο γνωρίζει ακριβώς ποιος είναι ο χρήστης χωρίς να μιλήσει ποτέ στον διακομιστή ελέγχου ταυτότητας ή σε μια βάση δεδομένων. Αυτό επιτρέπει στην υποδομή να κλιμακώνεται απεριόριστα χωρίς εμπόδια.
The Dark Side: Token Invalidation
Τα JWT δεν είναι τέλεια. Η μεγαλύτερη δύναμή τους (το ότι είναι ανιθαγενείς) είναι και η μεγαλύτερη αδυναμία τους. Επειδή ο διακομιστής δεν διατηρεί αρχείο ενεργών διακριτικών, δεν μπορείτε εύκολα να αποσυνδέσετε έναν χρήστη ή να ακυρώσετε ένα συγκεκριμένο διακριτικό πριν λήξει.
Εάν ένας χάκερ κλέψει το JWT ενός χρήστη, ο χάκερ έχει πλήρη πρόσβαση μέχρι να εξαντληθεί η χρονική σήμανση λήξης του διακριτικού. Για να μετριάσουν αυτόν τον κίνδυνο, οι μηχανικοί ασφαλείας χρησιμοποιούν ένα σύστημα δύο τόνων:
- Διακριτικά πρόσβασης: Μικρής διάρκειας JWT (π.χ. 15 λεπτά) που χρησιμοποιούνται για αιτήματα API.
- Ανανέωση διακριτικών: Διαρκή, κρατικά διακριτικά αποθηκευμένα με ασφάλεια, που χρησιμοποιούνται αυστηρά για να ζητηθούν νέα διακριτικά πρόσβασης. Εάν ένας λογαριασμός παραβιαστεί, ο διακομιστής ανακαλεί το Refresh Token και το Access Token του χάκερ θα πεθάνει φυσικά σε 15 λεπτά.
Συχνές Ερωτήσεις (FAQ)
Πού πρέπει να αποθηκεύσω ένα JWT στο μπροστινό μέρος;
Η αποθήκευση JWT στο localStorage τα καθιστά ευάλωτα σε επιθέσεις Cross-Site Scripting (XSS). Το πιο ασφαλές μέρος για να αποθηκεύσετε ένα JWT σε ένα πρόγραμμα περιήγησης ιστού βρίσκεται μέσα σε ένα cookie HttpOnly, το οποίο εμποδίζει την πρόσβαση σε αυτό της JavaScript.
Τι συμβαίνει εάν διαρρεύσει το μυστικό κλειδί του διακομιστή μου;
Καταστροφή. Εάν ένας χάκερ αποκτήσει το μυστικό κλειδί HMAC ή το ιδιωτικό κλειδί RSA, μπορεί να δημιουργήσει έγκυρα JWT με όποιο ωφέλιμο φορτίο θέλει. Θα μπορούσαν να δημιουργήσουν διακριτικά δίνοντας στον εαυτό τους προνόμια "Super Admin" και ο διακομιστής σας θα τα αποδεχόταν ως έγκυρα. Πρέπει να περιστρέψετε τα κλειδιά σας αμέσως.
Είναι τα JWT πιο γρήγορα από τα cookie περιόδου λειτουργίας;
Όχι απαραίτητα. Τα JWT είναι σημαντικά μεγαλύτερα σε μέγεθος αρχείου από ένα αναγνωριστικό περιόδου σύνδεσης 32 χαρακτήρων, πράγμα που σημαίνει ότι καταναλώνουν περισσότερο εύρος ζώνης δικτύου σε κάθε αίτημα. Το πλεονέκτημα της ταχύτητάς τους προέρχεται εξ ολοκλήρου από την παράκαμψη των αναζητήσεων της βάσης δεδομένων στο backend.