Menu
CoddyTech

Giriş Gerektiren Rotalar

Coddy'nin Node.js Journey'sinin Kimlik Doğrulama ve Güvenlik bölümünün bir parçası. Ders 6 / 17.

Her özel rota, GET /me isteğindeki oturum sorgulamasına ihtiyaç duyar. Her rotaya kopyalanırsa bir gün unutulur ve o rota herkese açık hâle gelir. Bunun yerine, bunu bir ara yazılım olarak bir kez yaz.

Ara yazılım rotadan önce çalışır. Ya yanıt verir ve işlemi durdurur ya da bulduğunu req üzerine ekleyip next() çağrısını yapar. Bunu, gereksinim duyan her rotaya işleyiciden önce aktar:

function requireAdult(req, res, next) {
    if (Number(req.query.age) < 18) {
        return res.status(403).json({ error: 'Adults only' });
    }
    req.adult = true;
    next();
}

app.get('/wines', requireAdult, (req, res) => res.json(wines));

return önemlidir: o olmazsa rota da çalışır.

challenge icon

Görev

Kolay
  • requireUser işlevini yaz: Geçerli bir oturum yoksa 401 { "error": "Log in first" } yanıtını ver; aksi hâlde req.user = { id, username } ata ve next() çağır.
  • GET /me, GET /notes ve POST /notes bu işlevi kullanır. Notlar owner: req.user.id değerini saklar ve GET /notes yalnızca sana ait notları listeler.

Oturum kapalıyken GET /notes isteği gönder, ardından giriş yap ve bir not ekle.

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 });
});

app.get('/me', async (req, res) => {
    const { sid } = parseCookies(req.get('cookie'));
    const session = sid && (await sessions.findOne({ _id: sid }));
    if (!session) {
        return res.status(401).json({ error: 'Log in first' });
    }
    const user = await users.findOne({ _id: session.userId });
    res.json({ username: user.username });
});

// Bu tarayıcının GET /visit isteğini kaç kez gönderdiğini 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. Şimdilik herkes bunları okuyabilir ve yazabilir.
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 iconKendini test et

Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.

Kimlik Doğrulama ve Güvenlik bölümündeki tüm dersler