التذكّر باستخدام ملفات تعريف الارتباط
جزء من قسم المصادقة والأمان في رحلة 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}`);
});التحدي
سهلينبغي أن يحصي GET /visit عدد مرات استدعاء هذا المتصفح له. لا يحفظ الخادم العدد. ينتقل العدد في ملف تعريف ارتباط، ويعيده المتصفح مع كل طلب.
- في
server.js، داخلGET /visit، اقرأ ملفات تعريف الارتباط التي أرسلها المتصفح، باستخدامparseCookiesكما يوضح الدرس. يوجد العدد في ملف تعريف الارتباط المسمىvisits. يصل على هيئة نص، مثل"2". في الزيارة الأولى يكون مفقودًا، وهذا يعني أن قيمته 0. - أضف 1 إلى العدد بوصفه رقمًا، بحيث تصبح
"2"هي3، لا"21". - عيّن ملف تعريف الارتباط
visitsإلى العدد الجديد، لكي يعيده المتصفح في المرة التالية. - أرسل العدد الجديد بوصفه رقمًا، لا نصًا:
{"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');
});
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس المصادقة والأمان
2الجلسات وملفات تعريف الارتباط
التذكّر باستخدام ملفات تعريف الارتباطالبحث عن جلسةجلسات تسجيل الدخولالمسارات المحمية بتسجيل الدخولتدرّب بنفسك: Playground لـ Express