JavaScript וקוקיז

JavaScript וקוקיז

מאמר זה מסביר על JavaScript וקוקיז.

נסביר הכל ביסודיות שלב אחר שלב: מהבסיס של קוקיז, קריאה וכתיבה, אבטחה ועד דוגמאות מעשיות.

YouTube Video

javascript-cookie.html
  1<!DOCTYPE html>
  2<html lang="en">
  3<head>
  4  <meta charset="UTF-8">
  5  <title>JavaScript &amp; HTML</title>
  6  <style>
  7    * {
  8        box-sizing: border-box;
  9    }
 10
 11    body {
 12        margin: 0;
 13        padding: 1em;
 14        padding-bottom: 10em;
 15        font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
 16        background-color: #f7f9fc;
 17        color: #333;
 18        line-height: 1.6;
 19    }
 20
 21    .container {
 22        max-width: 800px;
 23        margin: 0 auto;
 24        padding: 1em;
 25        background-color: #ffffff;
 26        border: 1px solid #ccc;
 27        border-radius: 10px;
 28        box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
 29    }
 30
 31    .container-flex {
 32        display: flex;
 33        flex-wrap: wrap;
 34        gap: 2em;
 35        max-width: 1000px;
 36        margin: 0 auto;
 37        padding: 1em;
 38        background-color: #ffffff;
 39        border: 1px solid #ccc;
 40        border-radius: 10px;
 41        box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
 42    }
 43
 44    .left-column, .right-column {
 45        flex: 1 1 200px;
 46        min-width: 200px;
 47    }
 48
 49    h1, h2 {
 50        font-size: 1.2rem;
 51        color: #007bff;
 52        margin-top: 0.5em;
 53        margin-bottom: 0.5em;
 54        border-left: 5px solid #007bff;
 55        padding-left: 0.6em;
 56        background-color: #e9f2ff;
 57    }
 58
 59    button {
 60        display: block;
 61        margin: 1em auto;
 62        padding: 0.75em 1.5em;
 63        font-size: 1rem;
 64        background-color: #007bff;
 65        color: white;
 66        border: none;
 67        border-radius: 6px;
 68        cursor: pointer;
 69        transition: background-color 0.3s ease;
 70    }
 71
 72    button:hover {
 73        background-color: #0056b3;
 74    }
 75
 76    #output {
 77        margin-top: 1em;
 78        background-color: #1e1e1e;
 79        color: #0f0;
 80        padding: 1em;
 81        border-radius: 8px;
 82        min-height: 200px;
 83        font-family: Consolas, monospace;
 84        font-size: 0.95rem;
 85        overflow-y: auto;
 86        white-space: pre-wrap;
 87    }
 88
 89    .highlight {
 90        outline: 3px solid #ffc107; /* yellow border */
 91        background-color: #fff8e1;  /* soft yellow background */
 92        transition: background-color 0.3s ease, outline 0.3s ease;
 93    }
 94
 95    .active {
 96        background-color: #28a745; /* green background */
 97        color: #fff;
 98        box-shadow: 0 0 10px rgba(40, 167, 69, 0.5);
 99        transition: background-color 0.3s ease, box-shadow 0.3s ease;
100    }
101  </style>
102</head>
103<body>
104    <div class="container">
105        <h1>JavaScript Console</h1>
106        <button id="executeBtn">Execute</button>
107        <div id="output"></div>
108    </div>
109
110    <script>
111        // Override console.log to display messages in the #output element
112        (function () {
113            // Override console.log
114            const originalLog = console.log;
115            console.log = function (...args) {
116                originalLog.apply(console, args);
117                const message = document.createElement('div');
118                message.textContent = args.map(String).join(' ');
119                output.appendChild(message);
120            };
121
122            // Override console.error
123            const originalError = console.error;
124            console.error = function (...args) {
125                originalError.apply(console, args);
126                const message = document.createElement('div');
127                message.textContent = args.map(String).join(' ');
128                message.style.color = 'red'; // Color error messages red
129                output.appendChild(message);
130            };
131        })();
132
133        document.getElementById('executeBtn').addEventListener('click', () => {
134            // Prevent multiple loads
135            if (document.getElementById('externalScript')) return;
136
137            const script = document.createElement('script');
138            script.src = 'javascript-cookie.js';
139            script.id = 'externalScript';
140            //script.onload = () => console.log('javascript-cookie.js loaded and executed.');
141            //script.onerror = () => console.log('Failed to load javascript-cookie.js.');
142            document.body.appendChild(script);
143        });
144    </script>
145</body>
146</html>

JavaScript וקוקיז

קוקי מתייחס ליחידות נתונים קטנות המאוחסנות בדפדפן של המשתמש. הם משמשים בעיקר למטרות הבאות:.

  • אימות משתמש (שמירה על מצב התחברות)
  • שמירת הגדרות המשתמש (שפה, ערכת נושא וכו')
  • מעקב (היסטוריית גלישה וכו')

ב-JavaScript ניתן לקרוא ולכתוב קוקיז באמצעות document.cookie.

יצירת (כתיבת) קוקיז

קוקיז נוצרים עם המבנה הבא:.

1document.cookie = "username=JohnDoe";
  • קוד זה שומר קוקי בשם "username=JohnDoe" בדפדפן.

יצירת קוקיז עם תאריך תפוגה

ניתן להגדיר תאריך תפוגה לקוקיז. אם לא מוגדר תאריך תפוגה, הקוקי הופך לקוקי סשן ומוסר כאשר הדפדפן נסגר.

1const date = new Date();
2date.setTime(date.getTime() + (7 * 24 * 60 * 60 * 1000)); // 7 days
3const cookieText = "username=JohnDoe; expires=" + date.toUTCString() + "; path=/; SameSite=None; Secure"
4document.cookie = cookieText;
5console.log(`Cookie Text  : ${cookieText}`);
6console.log(`Cookie Value : ${document.cookie}`);
  • מאפיין expires מגדיר את תאריך התפוגה של הקוקי בפורמט UTC.
  • מאפיין path מגדיר את הנתיב שבו יישלח הקוקי. / מציין את כל האתר.
  • אם תציין SameSite=None, העוגיה תישלח גם בבקשות בין אתרים. עם זאת, במקרה זה עליך תמיד לכלול את המאפיין Secure.
  • ציון Secure מגביל את העוגיה לתקשורת HTTPS בלבד, מה שמגביר את האבטחה.
  • על ידי התייחסות ל-document.cookie, תוכל לקבל את כל העוגיות הזמינות בדף הנוכחי כמחרוזת.
  • בעזרת console.log תוכל לבדוק את ההבדלים בין ערכי העוגיות שנקבעו בדפדפן לבין הערכים שניתן לשלוף.

קבלת (קריאת) קוקיז

ניתן לקבל את כל הקוקיז כמחרוזת על ידי document.cookie.

1const date = new Date();
2date.setTime(date.getTime() + (7 * 24 * 60 * 60 * 1000)); // 7 days
3document.cookie = "theme=dark; expires=" + date.toUTCString() + "; path=/; SameSite=None; Secure"
4
5console.log(document.cookie);
6// Output: "username=JohnDoe; theme=dark"
  • הערך שמוחזר מ-document.cookie הוא מחרוזת אחת שבה כל העוגיות שרשראות בפורמט 'מפתח=ערך;'.
  • נוח להשתמש בפונקציה כדי לנתח את המחרוזת הזו ולחלץ את הערך הרצוי.

פונקציה לקבלת הערך של קוקי

 1function getCookie(name) {
 2    const cookies = document.cookie.split('; ');
 3    for (const cookie of cookies) {
 4        const [key, value] = cookie.split('=');
 5        if (key === name) {
 6            return decodeURIComponent(value);
 7        }
 8    }
 9    return null;
10}
11
12console.log(getCookie("username")); // "JohnDoe"
  • פונקציה זו מפצלת את המפתחות והערכים בעזרת split() ומחזירה את הערך אם הוא תואם למפתח שצוין.
  • על ידי שימוש ב-decodeURIComponent, תוכל לשלוף תווים מקודדים כראוי.
  • אם המפתח המתאים לא קיים, מוחזר null.

מחיקת קוקיז

ניתן למחוק קוקי על ידי הגדרת תאריך התפוגה שלו לתאריך בעבר.

1document.cookie = "username=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/; SameSite=None; Secure";
2
3console.log(document.cookie);
4// Output: "theme=dark"
  • על ידי הקצאת ערך ריק ל-username והגדרת תאריך פקיעה לתאריך עבר, העוגיה תימחק.
  • בעת מחיקת עוגיה, עליך גם להתאים את המאפיינים של path, SameSite ו-Secure לאלו שהיו בשימוש בעת יצירתה.
  • בדוגמה זו, username נמחק, ועוגיות אחרות כגון theme=dark נשארות.

אפשרויות של קוקי

ניתן להגדיר אפשרויות שונות לשליטה בהתנהגות של קוקי. העיקריות הן:.

מגדיר את תאריך התפוגה של הקוקי בפורמט UTC. אם לא מוגדר, הקוקי הופך לקוקי סשן ומוסר כאשר הדפדפן נסגר.

מגדיר את תאריך התפוגה של הקוקי בשניות. אפשרות זו גוברת על `expires`.

מגדיר את הנתיב שלגביו יישלח הקוקי. לדוגמה, אם תגדיר `/admin`, הקוקי יישלח רק לעמודים בנתיב זה.

מגדיר את הדומיין שעבורו הקוקי תקף. בדרך כלל מוגדר לדומיין הנוכחי, אך אפשר להחיל אותו על כל הסאבדומיינים כמו `.example.com`.

כאשר מאפיין זה מוגדר, הקוקי נשלח רק דרך HTTPS. למען אבטחה מוגברת, תמיד יש להגדיר מאפיין זה עבור מידע רגיש.

שולט האם הקוקיז יישלחו בבקשות בין אתרים. ניתן להגדיר אחד משלושה ערכים:.

- `Strict`
    קוקיז נשלחים רק עבור בקשות מהאתר עצמו.

- `Lax`
    קוקיז נשלחים עבור ניווט רגיל אך יש מגבלות מסוימות.

- `None`
    קוקיז יכולים להישלח גם בבקשות בין אתרים. עם זאת, יש להגדיר גם את המאפיין `Secure`.

דוגמה: קוקי מאובטח

1document.cookie = "sessionId=abc123; secure; SameSite=Strict";
  • אם תציין secure, העוגיה תישלח רק דרך תקשורת HTTPS.
  • אם תציין SameSite=Strict, העוגיה לא תישלח בבקשות בין אתרים, דבר ההופך אותה ליעילה כהגנה מפני CSRF.
  • מאפייני אבטחה כאלה חיוניים לעוגיות חשובות המשמשות לאימות או לניהול סשנים.

קידוד ופענוח

מאחר שערכי קוקי יכולים לכלול תווים מיוחדים, בטוח יותר להשתמש ב-encodeURIComponent.

1const date = new Date();
2date.setTime(date.getTime() + (7 * 24 * 60 * 60 * 1000)); // 7 days
3
4const username = "JohnDoe";
5document.cookie =
6    "username=" + encodeURIComponent(username) +
7    "; max-age=604800; path=/; SameSite=None; Secure";
8
9console.log(decodeURIComponent(getCookie("username"))); // "JohnDoe"
  • באמצעות encodeURIComponent, תוכל לאחסן בבטחה רווחים, סימנים מיוחדים וכדומה בעוגיה.
  • בעת שליפתה, השתמש ב-decodeURIComponent כדי להחזיר את המחרוזת המקורית.
  • בדוגמה זו נעשה שימוש ב-max-age=604800 כדי להגדיר את תקופת הפקיעה לשבעה ימים (604,800 שניות). זוהי שיטה לציון תאריך פקיעה, בדומה ל-expires. את max-age ניתן לציין בשניות ולעיתים קל יותר להשתמש בו.

דוגמה מעשית: שמירה וטעינה של ערכת נושא

הבא הוא דוגמה לשמירת ערכת הנושא שבחר המשתמש בתוך קוקי והפעלה אוטומטית שלה בביקור הבא.

 1function setTheme(theme) {
 2    document.cookie =
 3        "theme=" + encodeURIComponent(theme) +
 4        "; max-age=604800; path=/; SameSite=None; Secure"; // 1 week
 5    applyTheme(theme);
 6}
 7
 8function applyTheme(theme) {
 9    document.body.style.backgroundColor = theme === "dark" ? "#333" : "#fff";
10    document.body.style.color = theme === "dark" ? "#fff" : "#000";
11}
12
13function getCookie(name) {
14    const cookies = document.cookie.split('; ');
15    for (const cookie of cookies) {
16        const [key, value] = cookie.split('=');
17        if (key === name) {
18            return decodeURIComponent(value);
19        }
20    }
21    return null;
22}
23
24const savedTheme = getCookie("theme");
25if (savedTheme) {
26    applyTheme(savedTheme);
27}
1<button onclick="setTheme('light')">Light</button>
2<button onclick="setTheme('dark')">Dark</button>
  • פונקציית setTheme שומרת את העיצוב שנבחר בעוגיה ומיד קוראת ל-applyTheme כדי לעדכן את המסך.
  • פונקציית applyTheme משנה את צבעי הרקע והטקסט של הגוף בהתאם לעיצוב.
  • בגלל ש-max-age=604800 מוגדר בדוגמה זו, הגדרת העיצוב נשמרת למשך שבוע אחד.
  • מכיוון שניתן לשמר את בחירת המשתמש כאשר הוא מבקר בעמוד שוב, חוויית המשתמש משתפרת.

מגבלות קוקיז ואזהרות

יש לשים לב לנקודות הבאות בעת שימוש בקוקיז:.

  • הגבלות גודל הגודל של קוקי בודד מוגבל לכ-4KB.

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

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

  • קוקיות שאינן נגישות מ-JavaScript קוקיות עם המאפיין HttpOnly אינן ניתנות לקריאה מ-JavaScript מסיבות אבטחה.

שרת ו-Cookie

1Set-Cookie: sessionId=abc123; HttpOnly; Secure; SameSite=Strict

חלק ממאפייני ה-Cookie, כגון HttpOnly, לא ניתן להגדירם דרך JavaScript. יש להגדיר אותם בצד השרת.

סיכום

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

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

  • קבע מאפייני אבטחה כיאות הגדר מאפיינים כמו Secure ו-SameSite כדי למנוע התקפות בין אתרים כגון XSS ו-CSRF.

  • קידוד ופענוח נתונים השתמש ב-encodeURIComponent ו-decodeURIComponent כדי לאחסן ולקרוא ערכי Cookie בצורה בטוחה כך שתווים מיוחדים ויפנית ייתמכו כראוי.

על ידי לימוד השימוש הנכון ב-Cookie, תוכל לבנות יישומי אינטרנט מתקדמים ובטוחים יותר.

תוכלו לעקוב אחר המאמר שלמעלה באמצעות Visual Studio Code בערוץ היוטיוב שלנו. נא לבדוק גם את ערוץ היוטיוב.

YouTube Video