Sesi Login
Termasuk bagian Autentikasi dan Keamanan dalam perjalanan Node.js di Coddy. Pelajaran 5 dari 17.
Login mengembalikan 200, lalu permintaan berikutnya sudah lupa siapa yang login. Sesi mengingatnya. Saat login, server membuat id yang tidak bisa ditebak siapa pun, menyimpan pengguna yang terkait dengannya, lalu mengirimkannya sebagai cookie. Setiap permintaan berikutnya mengirimkan id itu kembali, lalu server mencarinya.
Id harus acak. Cookie yang menyimpan nama pengguna memungkinkan siapa pun mengetik Cookie: sid=ada dan menjadi Ada. randomBytes(24) menghasilkan 192 bit acak. Atur cookie ke httpOnly agar script di halaman tidak dapat membacanya.
const cartId = randomBytes(24).toString('base64url');
await carts.insertOne({ _id: cartId, items: [] });
res.cookie('cart', cartId, { httpOnly: true });
// pada permintaan berikutnya
const cart = await carts.findOne({ _id: parseCookies(req.get('cookie')).cart });Tantangan
MudahPOST /loginmenyimpan{ _id: sid, userId }disessionsdan menetapkan cookiesiddenganhttpOnly, menggunakanrandomBytes(24).toString('base64url').GET /memengembalikan{ username }untuk sesi tersebut, atau 401{ "error": "Log in first" }.
Buat akun, login, kirim GET /me, lalu lihat Data.
Coba sendiri
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 });
});
// Menghitung berapa kali browser ini memanggil GET /visit.
app.get('/visit', (req, res) => {
const cookies = parseCookies(req.get('cookie'));
const visits = Number(cookies.visits ?? 0) + 1;
res.cookie('visits', String(visits));
res.json({ visits });
});
// Catatan. Untuk saat ini, siapa pun bisa membaca dan menulisnya.
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');
});
Semua pelajaran di Autentikasi dan Keamanan
4Pemilik dan Keamanan
Hanya CatatanmuPeran AdminLatihan sendiri: Playground Express