Express.js to wszechstronny framework backendowy dla Node.js, często używany do budowania aplikacji webowych i API. Dziś zajmiemy się bardziej zaawansowanymi tematami, które pomogą w tworzeniu bezpiecznych i funkcjonalnych aplikacji. Obejrzymy: autoryzację i autentykację z JWT, upload plików z Multerem, oraz walidację danych za pomocą express-validator.
Autoryzacja i Autentykacja
Wprowadzenie do JWT
JWT (JSON Web Tokens) jest popularnym sposobem autentykacji użytkowników w aplikacjach webowych. Token JWT jest kryptograficznie zabezpieczonym ładunkiem danych, który można przekazać między klientem a serwerem, aby sprawdzić autoryzację. Składa się z trzech części:
- Nagłówek (Header) – zawiera informacje o algorytmie szyfrowania.
- Ładunek (Payload) – przechowuje dane o użytkowniku.
- Podpis (Signature) – używany do weryfikacji integralności tokena.
Aby zainstalować JWT w Express.js, użyjemy biblioteki jsonwebtoken:
npm install jsonwebtoken bcryptjs
bcryptjs jest narzędziem do szyfrowania haseł.
Implementacja Systemu Rejestracji i Logowania
Najpierw utworzymy dwa endpointy: jeden do rejestracji użytkownika, a drugi do logowania.
Rejestracja Użytkownika
const express = require('express');
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
const User = require('./models/User'); // Zakładamy, że mamy model User
const router = express.Router();
// Rejestracja użytkownika
router.post('/register', async (req, res) => {
try {
const { username, password } = req.body;
// Hashowanie hasła
const hashedPassword = await bcrypt.hash(password, 10);
// Tworzenie nowego użytkownika
const user = new User({ username, password: hashedPassword });
await user.save();
res.status(201).json({ message: 'Użytkownik zarejestrowany pomyślnie' });
} catch (error) {
res.status(400).json({ message: error.message });
}
});
Logowanie
// Logowanie użytkownika
router.post('/login', async (req, res) => {
try {
const { username, password } = req.body;
// Znajdź użytkownika
const user = await User.findOne({ username });
if (!user) {
return res.status(400).json({ message: 'Nieprawidłowa nazwa użytkownika lub hasło' });
}
// Sprawdź hasło
const isMatch = await bcrypt.compare(password, user.password);
if (!isMatch) {
return res.status(400).json({ message: 'Nieprawidłowa nazwa użytkownika lub hasło' });
}
// Generowanie tokena JWT
const token = jwt.sign({ id: user._id }, 'sekretnyklucz', { expiresIn: '1h' });
res.json({ token });
} catch (error) {
res.status(400).json({ message: error.message });
}
});
Middleware do Ochrony Tras
Aby zabezpieczyć dostęp do pewnych tras, możemy stworzyć middleware, który będzie weryfikował token JWT:
// middleware/auth.js
const jwt = require('jsonwebtoken');
const auth = (req, res, next) => {
const token = req.header('Authorization')?.split(' ')[1];
if (!token) {
return res.status(401).json({ message: 'Brak tokena, autoryzacja odrzucona' });
}
try {
const decoded = jwt.verify(token, 'sekretnyklucz');
req.user = decoded;
next();
} catch (error) {
res.status(401).json({ message: 'Token jest nieprawidłowy' });
}
};
module.exports = auth;
Teraz możemy używać tego middleware’u, aby chronić trasy, np.:
const auth = require('./middleware/auth');
router.get('/profile', auth, (req, res) => {
res.json({ message: 'Dostęp do profilu użytkownika jest chroniony' });
});
Obsługa Plików
Upload Plików za Pomocą Multer
Multer to middleware, który ułatwia przesyłanie plików w Express.js. Zainstaluj go komendą:
npm install multer
Tworzymy middleware Multera:
const multer = require('multer');
// Konfiguracja przechowywania plików
const storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, 'uploads/');
},
filename: (req, file, cb) => {
cb(null, `${Date.now()}-${file.originalname}`);
},
});
const upload = multer({ storage });
const router = express.Router();
// Endpoint do uploadu plików
router.post('/upload', upload.single('file'), (req, res) => {
res.json({ message: 'Plik został pomyślnie przesłany', file: req.file });
});
W tym przykładzie konfigurujemy multer do przechowywania plików w katalogu uploads/, a plik będzie miał unikalną nazwę opartą na aktualnym czasie.
Obsługa Zasobów Statycznych (express.static)
Jeśli chcemy udostępniać publicznie przesłane pliki lub inne zasoby (np. obrazy, CSS, JavaScript), możemy użyć wbudowanego middleware:
app.use('/uploads', express.static('uploads'));
Dzięki temu każdy plik w katalogu uploads/ będzie dostępny pod adresem http://localhost:3000/uploads/{nazwa_pliku}.
Walidacja Danych
Wprowadzenie do express-validator
express-validator to popularne narzędzie do walidacji danych przychodzących w żądaniach. Aby go zainstalować:
npm install express-validator
Implementacja Walidacji Danych
Użyjemy express-validator, aby upewnić się, że dane dostarczane przez użytkowników spełniają nasze wymagania. Przykład walidacji przy rejestracji użytkownika:
const { body, validationResult } = require('express-validator');
router.post('/register', [
body('username').isLength({ min: 5 }).withMessage('Nazwa użytkownika musi mieć co najmniej 5 znaków'),
body('password').isLength({ min: 8 }).withMessage('Hasło musi mieć co najmniej 8 znaków'),
], async (req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
// Dalej postępujemy z logiką rejestracji
try {
const { username, password } = req.body;
const hashedPassword = await bcrypt.hash(password, 10);
const user = new User({ username, password: hashedPassword });
await user.save();
res.status(201).json({ message: 'Użytkownik zarejestrowany pomyślnie' });
} catch (error) {
res.status(400).json({ message: error.message });
}
});
W powyższym kodzie walidujemy, czy username ma przynajmniej 5 znaków, a password przynajmniej 8 znaków. Jeśli walidacja się nie powiedzie, zwracamy odpowiedni komunikat.
Podsumowanie
Dziś omówiliśmy bardziej zaawansowane funkcje Express.js, które są kluczowe dla bezpiecznego i funkcjonalnego rozwoju aplikacji:
- Autoryzacja i autentykacja z JWT – stworzyliśmy system rejestracji, logowania i ochrony tras.
- Obsługa plików z Multerem – przesyłanie plików stało się łatwe dzięki Multer.
- Walidacja danych z express-validator – upewniliśmy się, że dane wprowadzane przez użytkowników są poprawne.
Dzięki temu Twoje aplikacje będą bardziej bezpieczne, funkcjonalne i skalowalne.