Ghi nhớ bằng cookie
Thuộc phần Xác thực và bảo mật trong hành trình Node.js của Coddy. Bài học 8 trên 24.
HTTP quên bạn giữa các yêu cầu: mỗi yêu cầu đến riêng lẻ, và máy chủ không thể biết yêu cầu đó đến từ cùng một trình duyệt. Cookie giải quyết vấn đề này. Máy chủ trả lời bằng một tiêu đề Set-Cookie, rồi trình duyệt gửi lại giá trị đó trong tiêu đề Cookie ở mọi yêu cầu tiếp theo đến trang web đó.
res.cookie(name, value) đặt một cookie. req.get('cookie') đọc tiêu đề Cookie mà trình duyệt gửi, dưới dạng một dòng văn bản. Express không đọc tiêu đề Cookie thay bạn (package cookie-parser sẽ làm việc đó), vì vậy cookies.js cung cấp cho bạn parseCookies. Mọi giá trị đều nhận được dưới dạng văn bản.
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}`);
});Thử thách
DễGET /visit cần đếm số lần trình duyệt này đã gọi nó. Máy chủ không lưu số đếm. Số đếm nằm trong cookie, và trình duyệt gửi lại cookie đó trong mỗi yêu cầu.
- Trong
server.js, ởGET /visit, hãy đọc cookie mà trình duyệt gửi, dùngparseCookiesnhư bài học hướng dẫn. Số đếm nằm trong cookie có tênvisits. Giá trị này được gửi dưới dạng văn bản, như"2". Trong lần truy cập đầu tiên, cookie này chưa có, nên số đếm là 0. - Cộng 1 vào số đếm dưới dạng số, để
"2"trở thành3, chứ không phải"21". - Đặt cookie
visitsthành số đếm mới, để lần sau trình duyệt gửi lại cookie đó. - Phản hồi bằng số đếm mới dưới dạng số, không phải văn bản:
{"visits": 3}.
Thử nhé: Nhấn Chạy. Gửi GET /visit: {"visits": 1}. Gửi lại lần nữa: {"visits": 2}. Gửi lần thứ ba: {"visits": 3}. Mở thẻ Tiêu đề của phản hồi đó: Set-Cookie cho biết visits=3; Path=/.
Tự làm thử
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 });
});
// Đếm số lần trình duyệt này gọi GET /visit.
app.get('/visit', (req, res) => {
const visits = 1;
res.json({ visits });
});
// Ghi chú. Hiện tại, ai cũng có thể đọc và viết ghi chú.
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');
});
Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.
Tất cả bài học trong Xác thực và bảo mật
2Phiên làm việc và cookie
Ghi nhớ bằng cookieTra cứu phiênPhiên đăng nhậpĐịnh tuyến sau khi đăng nhậpTự luyện tập: Playground Express