const BlockedDevice = require('../models/BlockedDevice'); /** * Middleware для проверки блокировки устройства * Должен использоваться перед аутентификацией */ const checkDeviceBlock = async (req, res, next) => { try { console.log('[DEVICE_CHECK] Проверка блокировки устройства'); // Получаем fingerprint устройства из заголовков запроса const deviceFingerprint = req.headers['x-device-fingerprint']; if (!deviceFingerprint) { console.log('[DEVICE_CHECK] Device fingerprint не предоставлен'); return res.status(400).json({ message: 'Требуется идентификация устройства для обеспечения безопасности', code: 'DEVICE_FINGERPRINT_REQUIRED' }); } console.log('[DEVICE_CHECK] Проверяем fingerprint:', deviceFingerprint.substring(0, 16) + '...'); // Проверяем, заблокировано ли устройство const blockedDevice = await BlockedDevice.isDeviceBlocked(deviceFingerprint); if (blockedDevice) { console.log('[DEVICE_CHECK] Устройство заблокировано:', { deviceId: blockedDevice._id, blockedAt: blockedDevice.blockedAt, reason: blockedDevice.reason }); // Записываем попытку обхода блокировки await blockedDevice.addBypassAttempt({ type: req.route?.path?.includes('/login') ? 'login' : req.route?.path?.includes('/register') ? 'register' : 'api_request', ipAddress: req.ip || req.connection.remoteAddress, userAgent: req.headers['user-agent'] }); // Возвращаем ошибку блокировки return res.status(403).json({ blocked: true, message: 'Доступ с данного устройства заблокирован', reason: blockedDevice.reason, blockedAt: blockedDevice.blockedAt, code: 'DEVICE_BLOCKED' }); } // Проверяем похожие заблокированные устройства const similarDevices = await BlockedDevice.findSimilarDevices(deviceFingerprint, 0.85); if (similarDevices.length > 0) { console.log('[DEVICE_CHECK] Найдены похожие заблокированные устройства:', similarDevices.length); // Повышаем уровень безопасности для похожих устройств req.securityRisk = 'HIGH'; req.similarBlockedDevices = similarDevices; // Можно добавить дополнительные проверки для подозрительных устройств // Например, CAPTCHA или дополнительную верификацию } // Сохраняем fingerprint в запросе для дальнейшего использования req.deviceFingerprint = deviceFingerprint; req.deviceInfo = { userAgent: req.headers['user-agent'], ipAddress: req.ip || req.connection.remoteAddress, screenResolution: req.headers['x-screen-resolution'], platform: req.headers['x-platform'], language: req.headers['x-language'], timezone: req.headers['x-timezone'] }; console.log('[DEVICE_CHECK] Устройство не заблокировано, продолжаем'); next(); } catch (error) { console.error('[DEVICE_CHECK] Ошибка при проверке блокировки устройства:', error); // В случае ошибки системы безопасности, блокируем доступ return res.status(500).json({ message: 'Ошибка системы безопасности. Попробуйте позже.', code: 'SECURITY_CHECK_ERROR' }); } }; /** * Middleware для записи информации об устройстве при успешной аутентификации */ const recordDeviceActivity = async (req, res, next) => { try { if (req.deviceFingerprint && req.user) { console.log('[DEVICE_RECORD] Записываем активность устройства для пользователя:', req.user._id); // Можно сохранить информацию об устройстве пользователя для анализа // Например, в отдельной коллекции UserDevices // Пока просто логируем console.log('[DEVICE_RECORD] Device fingerprint:', req.deviceFingerprint.substring(0, 16) + '...'); console.log('[DEVICE_RECORD] Device info:', req.deviceInfo); } next(); } catch (error) { console.error('[DEVICE_RECORD] Ошибка при записи активности устройства:', error); // Не блокируем запрос из-за ошибки записи next(); } }; /** * Функция для блокировки устройства пользователя */ const blockUserDevice = async (userId, adminId, reason, deviceFingerprint = null) => { try { console.log('[BLOCK_DEVICE] Блокировка устройства пользователя:', userId); if (!deviceFingerprint) { // Если fingerprint не предоставлен, нужно найти его в активных сессиях // Это более сложная задача, требующая отслеживания активных сессий throw new Error('Device fingerprint не предоставлен для блокировки'); } const deviceInfo = { // Получаем дополнительную информацию об устройстве из базы данных или сессии // Это может быть реализовано через отслеживание активных подключений }; const blockedDevice = await BlockedDevice.blockDevice({ deviceFingerprint, blockedBy: adminId, blockedUserId: userId, reason, deviceInfo }); console.log('[BLOCK_DEVICE] Устройство заблокировано:', blockedDevice._id); return blockedDevice; } catch (error) { console.error('[BLOCK_DEVICE] Ошибка при блокировке устройства:', error); throw error; } }; /** * Функция для разблокировки устройства */ const unblockDevice = async (deviceFingerprint, adminId, reason) => { try { console.log('[UNBLOCK_DEVICE] Разблокировка устройства:', deviceFingerprint.substring(0, 16) + '...'); const blockedDevice = await BlockedDevice.findOne({ deviceFingerprint, isActive: true }); if (!blockedDevice) { throw new Error('Заблокированное устройство не найдено'); } await blockedDevice.unblock(adminId, reason); console.log('[UNBLOCK_DEVICE] Устройство разблокировано'); return blockedDevice; } catch (error) { console.error('[UNBLOCK_DEVICE] Ошибка при разблокировке устройства:', error); throw error; } }; /** * Функция для получения информации о заблокированных устройствах */ const getBlockedDevices = async (filters = {}) => { try { const { page = 1, limit = 20, sortBy = 'blockedAt', sortOrder = 'desc', isActive = true, userId } = filters; const query = { isActive }; if (userId) { query.blockedUserId = userId; } const skip = (page - 1) * limit; const sort = { [sortBy]: sortOrder === 'desc' ? -1 : 1 }; const devices = await BlockedDevice.find(query) .populate('blockedBy', 'name email') .populate('blockedUserId', 'name email') .sort(sort) .skip(skip) .limit(limit); const total = await BlockedDevice.countDocuments(query); return { devices, pagination: { currentPage: page, totalPages: Math.ceil(total / limit), totalItems: total, itemsPerPage: limit } }; } catch (error) { console.error('[GET_BLOCKED_DEVICES] Ошибка при получении заблокированных устройств:', error); throw error; } }; module.exports = { checkDeviceBlock, recordDeviceActivity, blockUserDevice, unblockDevice, getBlockedDevices };