From 489f718fec2a8458cdb75d606855933102dc542a Mon Sep 17 00:00:00 2001 From: Professional Date: Mon, 26 May 2025 18:05:58 +0700 Subject: [PATCH] =?UTF-8?q?=D1=84=D0=B8=D0=BA=D1=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main.js | 4 +- src/services/deviceSecurity.js | 23 +++++++++++ src/utils/deviceFingerprint.js | 75 ++++++++++++++++------------------ 3 files changed, 61 insertions(+), 41 deletions(-) diff --git a/src/main.js b/src/main.js index 486b290..d5f24ab 100644 --- a/src/main.js +++ b/src/main.js @@ -29,8 +29,8 @@ const isBrowser = typeof window !== 'undefined' && typeof document !== 'undefine console.log('Инициализация системы безопасности устройств...'); await deviceSecurityService.initialize(); - // Подписываемся на события блокировки устройства - deviceSecurityService.onDeviceBlocked(handleDeviceBlocked); + // Исправлено: Используем правильный метод onDeviceBlock вместо onDeviceBlocked + deviceSecurityService.onDeviceBlock(handleDeviceBlocked); console.log('Система безопасности устройств инициализирована'); diff --git a/src/services/deviceSecurity.js b/src/services/deviceSecurity.js index 34628ba..dff8ff7 100644 --- a/src/services/deviceSecurity.js +++ b/src/services/deviceSecurity.js @@ -18,6 +18,7 @@ class DeviceSecurityService { this.suspiciousActivities = []; this.lastFingerprintCheck = null; this.checkInterval = null; + this.blockCallbacks = []; // Добавляем массив для хранения колбэков блокировки // Настройки мониторинга this.config = { @@ -277,6 +278,17 @@ class DeviceSecurityService { } } + /** + * Добавляет обработчик события блокировки устройства + * @param {Function} callback Функция обратного вызова + */ + onDeviceBlock(callback) { + if (typeof callback === 'function' && !this.blockCallbacks.includes(callback)) { + this.blockCallbacks.push(callback); + console.log('[DeviceSecurity] Добавлен обработчик события блокировки устройства'); + } + } + /** * Обработка блокировки устройства */ @@ -289,6 +301,17 @@ class DeviceSecurityService { // Очищаем локальные данные this.clearLocalData(); + // Вызываем все зарегистрированные обработчики + if (this.blockCallbacks && this.blockCallbacks.length > 0) { + this.blockCallbacks.forEach(callback => { + try { + callback(blockInfo); + } catch (e) { + console.error('[DeviceSecurity] Ошибка в обработчике блокировки устройства:', e); + } + }); + } + // Показываем уведомление пользователю this.showBlockedNotification(blockInfo); diff --git a/src/utils/deviceFingerprint.js b/src/utils/deviceFingerprint.js index 2b694fc..2d8b117 100644 --- a/src/utils/deviceFingerprint.js +++ b/src/utils/deviceFingerprint.js @@ -175,54 +175,51 @@ class DeviceFingerprint { return new Promise((resolve) => { try { + // Если AudioContext недоступен, просто пропускаем этот шаг if (!window.AudioContext && !window.webkitAudioContext) { + console.warn('[DeviceFingerprint] AudioContext не поддерживается'); + this.components.set('audio', 'not-available'); resolve(); return; } - const AudioContext = window.AudioContext || window.webkitAudioContext; - const context = new AudioContext(); - - const oscillator = context.createOscillator(); - const analyser = context.createAnalyser(); - const gainNode = context.createGain(); - const scriptProcessor = context.createScriptProcessor(4096, 1, 1); - - oscillator.type = 'triangle'; - oscillator.frequency.value = 10000; - - gainNode.gain.value = 0; - - oscillator.connect(analyser); - analyser.connect(scriptProcessor); - scriptProcessor.connect(gainNode); - gainNode.connect(context.destination); - - scriptProcessor.onaudioprocess = async (event) => { - const bins = new Float32Array(analyser.frequencyBinCount); - analyser.getFloatFrequencyData(bins); - - const audioHash = await this.hashString(bins.slice(0, 50).join(',')); - this.components.set('audio', audioHash); - - oscillator.disconnect(); - context.close(); - resolve(); + // Создаём аудио хэш на основе доступных properties AudioContext + // без использования ScriptProcessorNode + const createAudioFingerprintFallback = () => { + try { + const AudioContext = window.AudioContext || window.webkitAudioContext; + const context = new AudioContext(); + + const audioProps = { + sampleRate: context.sampleRate, + state: context.state, + baseLatency: context.baseLatency || 0, + outputLatency: context.outputLatency || 0 + }; + + // Преобразуем эти свойства в хэш + const audioHash = this.simpleHash(JSON.stringify(audioProps)); + this.components.set('audio', audioHash); + + // Закрываем context + if (context.state !== 'closed') { + context.close(); + } + + resolve(); + } catch (e) { + console.warn('[DeviceFingerprint] Ошибка в audio fingerprint fallback:', e); + this.components.set('audio', 'error'); + resolve(); + } }; - oscillator.start(); - - // Таймаут на случай проблем - setTimeout(() => { - try { - oscillator.disconnect(); - context.close(); - } catch (e) {} - resolve(); - }, 1000); - + // Используем безопасный fallback вместо устаревшего ScriptProcessor + // и AudioWorklet (который требует отдельного файла и https) + createAudioFingerprintFallback(); } catch (e) { console.warn('[DeviceFingerprint] Не удалось создать audio fingerprint:', e); + this.components.set('audio', 'error'); resolve(); } });