/
varsl
/
HTML-CSS
Обзор
Документация
Войти
/
varsl
/
HTML-CSS
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
backend/middleware/authMiddleware.js
244 строки
8 KB
varsl
Создание middleware для аутентификации и валидации
21 дек 2025, 23:51
21 дек 2025, 23:51
a879b99
Код
Авторство
О чём код?
const jwt = require('jsonwebtoken'); const { jwtSecret } = require('../config'); const User = require('../models/User'); const authMiddleware = async (req, res, next) => { try { // Получаем токен из заголовка Authorization const authHeader = req.header('Authorization'); if (!authHeader) { return res.status(401).json({ success: false, message: 'Требуется авторизация. Пожалуйста, войдите в систему.' }); } // Проверяем фортокена const token = authHeader.replace('Bearer ', ''); if (!token) { return res.status(401).json({ success: false, message: 'Неверный формат токена' }); } // Верифицируем токен const decoded = jwt.verify(token, jwtSecret); // Ищем пользователя в базе данных const user = await User.findById(decoded.userId); if (!user) { return res.status(401).json({ success: false, message: 'Пользователь не найден' }); } // Добавляем пользователя в объект запроса req.user = user; req.token = token; next(); } catch (error) { console.error('Auth middleware error:', error.message); // Обработка различных ошибок JWT if (error.name === 'JsonWebTokenError') { return res.status(401).json({ success: false, message: 'Неверный токен' }); } if (error.name === 'TokenExpiredError') { return res.status(401).json({ success: false, message: 'Срок действия токена истек. Пожалуйста, войдите снова.' }); } // Общая ошибка сервера res.status(500).json({ success: false, message: 'Ошибка сервера при проверке авторизации' }); } }; // Middleware для проверки прав администратора const adminMiddleware = async (req, res, next) => { try { // Проверяем, что пользователь авторизован if (!req.user) { return res.status(401).json({ success: false, message: 'Требуется авторизация' }); } // Проверяем роль пользователя if (req.user.role !== 'admin') { return res.status(403).json({ success: false, message: 'Недостаточно прав. Требуются права администратора.' }); } next(); } catch (error) { console.error('Admin middleware error:', error); res.status(500).json({ success: false, message: 'Ошибка при проверке прав администратора' }); } }; // Middleware для проверки, что пользователь является владельцем ресурса const ownerMiddleware = (resourceUserIdField = 'user_id') => { return async (req, res, next) => { try { // Для администраторов пропускаем проверку if (req.user && req.user.role === 'admin') { return next(); } // Получаем ID пользователя из ресурса (например, из параметров запроса) let resourceUserId; if (req.params[resourceUserIdField]) { resourceUserId = req.params[resourceUserIdField]; } else if (req.body[resourceUserIdField]) { resourceUserId = req.body[resourceUserIdField]; } else if (req.query[resourceUserIdField]) { resourceUserId = req.query[resourceUserIdField]; } // Если ID ресурса не указан, пропускаем if (!resourceUserId) { return next(); } // Проверяем, что пользователь является владельцем if (parseInt(resourceUserId) !== req.user.id) { return res.status(403).json({ success: false, message: 'У вас нет прав для выполнения этого действия' }); } next(); } catch (error) { console.error('Owner middleware error:', error); res.status(500).json({ success: false, message: 'Ошибка при проверке прав доступа' }); } }; }; // Middleware для проверки, что пользователь не является гостем const authenticatedOnly = (req, res, next) => { if (!req.user) { return res.status(401).json({ success: false, message: 'Эта функция доступна только для авторизованных пользователей' }); } next(); }; // Middleware для проверки, что пользователь не является администратором const notAdminMiddleware = (req, res, next) => { if (req.user && req.user.role === 'admin') { return res.status(403).json({ success: false, message: 'Эта функция недоступна для администраторов' }); } next(); }; // Middleware для проверки CSRF токена (упрощенная версия) const csrfMiddleware = (req, res, next) => { // Для GET запросов пропускаем проверку if (req.method === 'GET') { return next(); } const csrfToken = req.headers['x-csrf-token'] || req.body._csrf; if (!csrfToken) { return res.status(403).json({ success: false, message: 'CSRF токен отсутствует' }); } // В реальном приложении здесь должна быть проверка токена // Для демо просто пропускаем next(); }; // Middleware для ограничения запросов (rate limiting) const rateLimitMiddleware = (options = {}) => { const { windowMs = 15 * 60 * 1000, // 15 минут max = 100, // максимум 100 запросов за окно message = 'Слишком много запросов. Попробуйте позже.' } = options; const requests = new Map(); return (req, res, next) => { const now = Date.now(); const ip = req.ip || req.connection.remoteAddress; if (!requests.has(ip)) { requests.set(ip, []); } const timestamps = requests.get(ip); // Удаляем старые записи while (timestamps.length > 0 && timestamps[0] <= now - windowMs) { timestamps.shift(); } // Проверяем лимит if (timestamps.length >= max) { return res.status(429).json({ success: false, message }); } // Добавляем текущий запрос timestamps.push(now); // Очистка старых записей (каждые 100 запросов) if (requests.size > 1000) { for (const [key, value] of requests.entries()) { if (value.length === 0 || value[value.length - 1] < now - windowMs) { requests.delete(key); } } } next(); }; }; module.exports = { authMiddleware, adminMiddleware, ownerMiddleware, authenticatedOnly, notAdminMiddleware, csrfMiddleware, rateLimitMiddleware };