לדלג לתוכן

אימות ואותנטיקציה - Session מול JWT

כל אתר עם התחברות מתמודד עם אותה בעיה בסיסית - איך המערכת זוכרת מי אתם בין בקשה לבקשה. HTTP הוא פרוטוקול חסר זיכרון, כל בקשה מגיעה בלי שום קשר לקודמת, אז צריך מנגנון שיגיד לשרת "זה אותו משתמש שהתחבר לפני רגע". שתי הגישות המרכזיות לפתור את זה הן Session ו-JWT, וההבדל ביניהן הוא בדיוק סוג ההחלטה שכל מפתח צד שרת נדרש להבין.

איך Session עובד

בגישת ה-session, כשמשתמש מתחבר, השרת יוצר רשומה שמייצגת אותו - בדרך כלל בזיכרון או ב-Redis - ומחזיר למשתמש מזהה session בעוגייה (cookie). בכל בקשה הבאה, הדפדפן שולח את העוגייה בחזרה, השרת בודק מול הרשומה השמורה מי המשתמש, ומחליט אם לאפשר את הפעולה.

היתרון המרכזי הוא שליטה מלאה. רוצים לנתק משתמש? פשוט מוחקים את הרשומה שלו, וכל הבקשות הבאות נכשלות מיד. הבעיה היא שהשרת צריך לשמור מצב (state) לכל משתמש מחובר, מה שמסבך קצת את התמונה כשיש כמה שרתים שמאזנים עומס ביניהם - כולם צריכים גישה לאותו מאגר sessions.

איך JWT עובד

ב-JWT הגישה הפוכה. במקום לשמור רשומה בשרת, כל המידע על המשתמש - מי הוא, מה ההרשאות שלו, מתי הטוקן פג - נשמר בתוך הטוקן עצמו, וחתום דיגיטלית כדי שאף אחד לא יוכל לשנות אותו בלי שהשרת יגלה. השרת לא צריך לזכור כלום. הוא מקבל טוקן, בודק שהחתימה תקינה, וסומך על מה שכתוב בפנים.

זה הופך את המערכת ל-stateless - כל שרת בכל רגע יכול לאמת טוקן בעצמו, בלי לפנות למאגר משותף. זה נוח מאוד במערכות עם הרבה שרתים, כי אין צורך בסנכרון מצב ביניהם.

המחיר הנסתר של JWT - ביטול טוקן

היתרון של JWT הוא גם החולשה שלו. מכיוון שהשרת לא שומר רשומה, אין דרך פשוטה "לבטל" טוקן שכבר הונפק. אם משתמש מתנתק, או שהתגלה שהחשבון שלו נפרץ, הטוקן עדיין תקף עד שהוא פג תוקף לבד. הפתרון הנפוץ הוא להשתמש בטוקנים קצרי טווח (כמה דקות), יחד עם refresh token נפרד שכן אפשר לבטל, ולחדש את הטוקן הקצר באמצעותו כל הזמן. זה מוסיף מורכבות, אבל שומר על היכולת לבטל גישה כשצריך.

מתי לבחור בכל גישה

Session מתאים כשהמערכת שלכם היא אפליקציית ווב מסורתית, עם צד שרת אחד או כמה שרתים שחולקים בקלות מאגר Redis, ואתם רוצים שליטה מיידית על ניתוק משתמשים - למשל מערכות עם דרישות אבטחה גבוהות שצריכות יכולת ביטול מיידית.

JWT מתאים יותר כשיש לכם API שמשרת כמה קליינטים שונים - אתר, אפליקציית מובייל, שירותים אחרים שקוראים ל-API - ובמיוחד כשהארכיטקטורה שלכם מבוססת מיקרוסרביסים שצריכים לאמת בקשות בלי לפנות כל פעם למאגר משותף. זו הסיבה ש-JWT כל כך נפוץ ב-API ציבוריים ובמערכות מבוזרות.

שילוב בין השתיים

הרבה מערכות מודרניות בכלל לא בוחרות אחת בלבד, אלא משלבות. משתמשים ב-JWT קצר טווח לגישה ל-API, אבל שומרים refresh token בצד השרת בצורה שדומה ל-session, כדי לשמור על יכולת ביטול. זה נותן את המהירות והפשטות של JWT בבקשות היומיומיות, בלי לוותר לגמרי על השליטה שיש ב-session.

הטעות הנפוצה ביותר

מפתחים רבים בוחרים JWT כי הוא נשמע "מודרני יותר", בלי לחשוב על הצורך האמיתי בביטול טוקן. אם המערכת שלכם קטנה, רצה על שרת אחד או שניים, ואין לכם צורך אמיתי בשירותים מרובים שצריכים לאמת עצמאית - session פשוט יותר, בטוח יותר להתחיל איתו, ופותר את הבעיה בלי הסיבוך של refresh tokens.

איך לומדים ליישם את זה נכון

הבנת ההבדל התיאורטי היא קלה, אבל ליישם אימות נכון בפרויקט אמיתי - עם הצפנת סיסמאות, ניהול טוקנים, והגנה מפני התקפות נפוצות - זה משהו שלומדים רק כשבונים מערכת אימות מקצה לקצה. בקורס צד-שרת בונים מערכת אימות שלמה, כולל שתי הגישות, ומבינים בדיוק מתי כל אחת מהן מתאימה.

יש לכם החלטה קונקרטית לקבל בפרויקט שלכם ולא בטוחים לאיזה כיוון ללכת? זה בדיוק סוג הדיון שקורה בדיסקורד שלנו.

הצטרפו לקהילה בדיסקורד

לסיכום

Session ו-JWT פותרים את אותה בעיה בשתי גישות שונות - האחת שומרת מצב בשרת ומקבלת שליטה, השנייה מוותרת על מצב ומקבלת קלות שימוש במערכות מבוזרות. אין תשובה נכונה אחת, יש רק התאמה נכונה לצרכים של המערכת שאתם בונים, ובשביל זה חשוב להבין את שתי הגישות לעומק, לא רק לשנן איזו מהן "יותר טובה".