JavaRush /Курсы /Модуль 3: React /Процесс создания и валидации JWT на сервере

Процесс создания и валидации JWT на сервере

Модуль 3: React
15 уровень , 1 лекция
Открыта

Зачем нужно генерировать и валидировать JWT

Для чёткого понимания давайте разберём сценарий. Представьте, что вы посетили веб-приложение (например, интернет-магазин). После успешного логина сервер выдаёт вам уникальный токен (JWT), который будет отправляться вместе с каждым запросом. Сервер, в свою очередь, использует этот токен для проверки вашей идентификации. Если токен валиден — сервер говорит: "Окей, могу доверять этому человеку". Если нет — вы попадёте на страницу логина.

Как работает создание JWT (немного теории перед практикой)

  1. Создание токена:

    • Сервер генерирует JWT, подписывая его секретным ключом.
    • Токен включает полезную нагрузку с данными о пользователе (например, id, email, роль).
    • Токен имеет срок действия exp, после которого становится недействительным.
  2. Валидация токена:

    • Каждый раз, когда клиент отправляет запрос с токеном, сервер проверяет подпись и срок действия.
    • Если подпись или срок невалидны — доступ закрывается.

Библиотека для работы с JWT

Для работы с JWT на сервере мы будем использовать популярную библиотеку jsonwebtoken. Она проста, удобна и хорошо документирована.

Установка

npm install jsonwebtoken

Не бойтесь, установка миниатюрная. В отличие от "node_modules", которая, кажется, весит больше, чем половина интернета.

Генерация JWT на сервере

Перейдём от слов к делу. Для начала создадим простое Express-приложение. Если у вас ещё нет проекта, создайте его:

mkdir jwt-auth-app
cd jwt-auth-app
npm init -y
npm install express jsonwebtoken body-parser

Создайте файл server.ts и напишите следующий код:

server.ts

import express, { Request, Response } from "express";
import jwt from "jsonwebtoken";

const app = express();
const PORT = 3000;

// Секретный ключ для подписи токенов
const JWT_SECRET = "supersecretkey"; // Никогда не используйте такую строчку в реальных проектах, храните секреты в .env.

app.use(express.json());

// Пример эндпоинта для генерации токена
app.post("/login", (req: Request, res: Response) => {
  const { username, password } = req.body;

  // Простая проверка данных (не для продакшена)
  if (username === "admin" && password === "12345") {
    // Полезная нагрузка токена
    const payload = { username };

    // Генерация токена
    const token = jwt.sign(payload, JWT_SECRET, { expiresIn: "1h" });

    return res.json({ token });
  }

  res.status(401).json({ message: "Invalid username or password" });
});

// Запуск сервера
app.listen(PORT, () => console.log(`Server running on http://localhost:${PORT}`));

Разбор кода

  • jwt.sign: используется для генерации токена. Первый аргумент — это полезная нагрузка, второй — секретный ключ, а третий — настройки (например, срок действия).
  • Секретный ключ: это строка, которая используется для подписи токена. Никогда не храните её в коде, всегда используйте переменные окружения.
  • Временный срок действия expiresIn: "1h": указывает, что токен будет действителен в течение 1 часа.

Теперь запустите сервер командой node server.ts (не забудьте компилировать TypeScript, если используете его). Отправьте POST-запрос на /login с телом:

{
  "username": "admin",
  "password": "12345"
}

Если всё работает правильно, вы получите токен. Поздравляю!

Валидация JWT на сервере

Собственно, теперь пришло время научиться проверять токены. Добавим новый защищённый маршрут /protected, который будет доступен только аутентифицированным пользователям.

server.ts

// Middleware для проверки токена
const authenticateToken = (req: Request, res: Response, next: Function) => {
  const authHeader = req.headers["authorization"];
  const token = authHeader && authHeader.split(" ")[1]; // Bearer <token>

  if (!token) {
    return res.status(401).json({ message: "Access token is missing" });
  }

  try {
    // Проверяем токен
    const payload = jwt.verify(token, JWT_SECRET);
    (req as any).user = payload; // Записываем данные в запрос
    next();
  } catch (error) {
    return res.status(403).json({ message: "Invalid token" });
  }
};

// Защищённый маршрут
app.get("/protected", authenticateToken, (req: Request, res: Response) => {
  res.json({ message: `Welcome, ${(req as any).user.username}!` });
});

Разбор кода

  • jwt.verify: проверяет токен на валидность, используя секретный ключ.
  • Bearer-токены: это стандартный способ передачи токенов в заголовках.
  • Middleware: используется для проверки токена перед тем, как пользователь получит доступ к защищённому ресурсу.

Теперь попробуйте отправить GET-запрос на /protected с заголовком:

Authorization: Bearer <ваш-токен>

Если токен валиден, вы получите сообщение приветствия. Если нет — ошибку.

Типичные ошибки

  1. Пропущенный токен: сервер вернёт ошибку Access token is missing, если в запросе отсутствует токен.
  2. Истёкший токен: если время жизни токена истекло, jwt.verify выбросит ошибку.
  3. Неверный секретный ключ: если токен был подписан другим ключом, сервер не сможет его проверить.
  4. Хранение токена в JavaScript-коде: никогда не храните секреты в коде! Используйте .env-переменные.
2
Задача
Модуль 3: React, 15 уровень, 1 лекция
Недоступна
Генерация JWT
Генерация JWT
Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ