Oturumu Kapatma
Coddy'nin Node.js Journey'sinin Kimlik Doğrulama ve Güvenlik bölümünün bir parçası. Ders 12 / 24.
Tanımlama bilgisini temizlemek yalnızca tarayıcıdan kimliği unutmasını ister. Kimliği paylaşılan bir bilgisayardan veya çalınmış bir tanımlama bilgisinden kopyalayan herkes, hâlâ çalışan bir anahtara sahiptir. Oturumu kapatmak için oturumun sunucudan silinmesi gerekir.
res.clearCookie(name), tarayıcıya bir tanımlama bilgisini silmesini söyler. 204 İçerik Yok durumu, işlemin başarılı olduğu ve geri gönderilecek hiçbir şey olmadığı anlamına gelir: res.status(204).end().
İşte ilgili bir rota; kullanıcının aynı anda tüm cihazlardan oturumunu kapatır:
app.post('/logout-everywhere', requireUser, async (req, res) => {
await sessions.deleteMany({ userId: new ObjectId(req.user.id) });
res.clearCookie('sid');
res.status(204).end();
});Görev
KolayOturumdan çıkmanın bir yolunu ekle. Çerezi silmek tek başına yeterli değildir; çünkü oturum kimliğini kopyalayan herkes onu kullanmaya devam edebilir. Bu nedenle sunucu da oturumu unutur.
server.jsdosyasınaPOST /logoutekle. İstek gövdesi gerekmez.sidçerezini oku. Çerez varsasessionsiçindeki oturumu o_idile sil.- Tarayıcıya
sidçerezini unutmasını söyle. - 204 durum koduyla ve gövde olmadan yanıt ver. 204 No Content, işlemin başarılı olduğu ve gönderilecek hiçbir şey bulunmadığı anlamına gelir. İstekte
sidçerezi olmasa bile 204 ile yanıt ver.
Deneyin: “Çalıştır”a bas. POST /signup, ardından POST /login gönder; her ikisinde de {"username": "ada", "password": "correct horse"} kullan. GET /me, {"username": "ada"} döndürür. POST /logout gönder: durum kodu 204 ve boş gövde. Yeniden GET /me gönder: durum kodu 401 ve {"error": "Log in first"}. Veriler'i aç: sessions boş. Bir kez daha POST /logout gönder: yine 204.
Kendin dene
import express from 'express';
import { randomBytes } from 'node:crypto';
import { parseCookies } from './cookies.js';
import { notes, sessions, 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' });
}
const sid = randomBytes(24).toString('base64url');
await sessions.insertOne({ _id: sid, userId: user._id, createdAt: new Date() });
res.cookie('sid', sid, { httpOnly: true });
res.json({ username: user.username });
});
// Oturum çerezinin kullanıcısını bulur veya 401 yanıtı verir.
async function requireUser(req, res, next) {
const { sid } = parseCookies(req.get('cookie'));
const session = sid && (await sessions.findOne({ _id: sid }));
const user = session && (await users.findOne({ _id: session.userId }));
if (!user) {
return res.status(401).json({ error: 'Log in first' });
}
req.user = { id: user._id.toHexString(), username: user.username };
next();
}
app.get('/me', requireUser, (req, res) => {
res.json({ username: req.user.username });
});
// Bu tarayıcının GET /visit isteğini kaç kez yaptığını sayar.
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 });
});
// Notlar: Her kullanıcı yalnızca kendi notlarını okur ve yazar.
app.get('/notes', requireUser, async (req, res) => {
res.json(await notes.find({ owner: req.user.id }).toArray());
});
app.post('/notes', requireUser, async (req, res) => {
const note = { owner: req.user.id, 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');
});
Kimlik Doğrulama ve Güvenlik bölümündeki tüm dersler
Kendi başına pratik yap: Express playground