Menu
CoddyTech

זכירה באמצעות Cookies

חלק מהיחידה אימות ואבטחה במסלול ה-Node.js של Coddy. שיעור 8 מתוך 24.

‏HTTP לא זוכר אותך בין בקשות: כל בקשה מגיעה לבדה, והשרת לא יכול לדעת שהיא הגיעה מאותו דפדפן. עוגייה פותרת את הבעיה. השרת משיב עם כותרת Set-Cookie, והדפדפן שולח את הערך בחזרה בכותרת Cookie בכל בקשה מאוחרת יותר לאתר הזה.

res.cookie(name, value) מגדירה עוגייה. req.get('cookie') קוראת את כותרת Cookie שהדפדפן שלח, כשורת טקסט אחת. Express לא קוראת בשבילך את כותרת Cookie (החבילה cookie-parser הייתה עושה זאת), לכן cookies.js מספקת לך את parseCookies. כל ערך מגיע כטקסט.

app.get('/theme/:name', (req, res) => {
    res.cookie('theme', req.params.name);
    res.send('Saved');
});

app.get('/', (req, res) => {
    const { theme = 'light' } = parseCookies(req.get('cookie'));
    res.send(`Your theme is ${theme}`);
});
challenge icon

אתגר

קל

GET /visit אמור לספור כמה פעמים הדפדפן הזה שלח אליו בקשה. השרת לא שומר את הספירה. הספירה עוברת בקובץ cookie, והדפדפן שולח אותו בחזרה בכל בקשה.

  1. ב־server.js, בתוך GET /visit, קרא את קובצי ה־cookie שהדפדפן שלח, באמצעות parseCookies כפי שמוצג בשיעור. הספירה נמצאת בקובץ ה־cookie ששמו visits. היא מגיעה כטקסט, כמו "2". בביקור הראשון היא חסרה, ולכן ערכה הוא 0.
  2. הוסף 1 לספירה כמספר, כך ש־"2" יהפוך ל־3, ולא ל־"21".
  3. הגדר את קובץ ה־cookie visits לערך הספירה החדש, כדי שהדפדפן ישלח אותו בחזרה בפעם הבאה.
  4. השב עם הספירה החדשה כמספר, ולא כטקסט: {"visits": 3}.

נסה זאת: לחץ על "שחק". שלח GET /visit: {"visits": 1}. שלח אותו שוב: {"visits": 2}. שלח אותו בפעם השלישית: {"visits": 3}. פתח את הכרטיסייה Headers של התגובה: Set-Cookie מציין visits=3; Path=/.

נסו בעצמכם

import express from 'express';
import { parseCookies } from './cookies.js';
import { notes, users } from './db.js';
import { hashPassword, verifyPassword } from './passwords.js';

const app = express();
app.use(express.json());

app.post('/signup', async (req, res) => {
    const username = String(req.body.username ?? '').trim().toLowerCase();
    const password = String(req.body.password ?? '');
    if (!username || password.length < 8) {
        return res.status(400).json({ error: 'Pick a username and a password of at least 8 characters' });
    }
    if (await users.findOne({ username })) {
        return res.status(409).json({ error: 'That username is taken' });
    }
    await users.insertOne({ username, passwordHash: await hashPassword(password) });
    res.status(201).json({ username });
});

app.post('/login', async (req, res) => {
    const username = String(req.body.username ?? '').trim().toLowerCase();
    const user = await users.findOne({ username });
    if (!user || !(await verifyPassword(String(req.body.password ?? ''), user.passwordHash))) {
        return res.status(401).json({ error: 'Wrong username or password' });
    }
    res.json({ username: user.username });
});

// סופר כמה פעמים הדפדפן הזה שלח בקשת GET לנתיב /visit.
app.get('/visit', (req, res) => {
    const visits = 1;
    res.json({ visits });
});

// פתקים. בינתיים כל אחד יכול לקרוא ולכתוב אותם.
app.get('/notes', async (req, res) => {
    res.json(await notes.find().toArray());
});

app.post('/notes', async (req, res) => {
    const note = { text: String(req.body.text ?? '') };
    await notes.insertOne(note);
    res.status(201).json(note);
});

app.listen(3000, () => {
    console.log('Vault is running on port 3000');
});
quiz iconבחנו את עצמכם

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

כל השיעורים ביחידה אימות ואבטחה

תרגלו בעצמכם: Express אונליין