This commit is contained in:
Professional 2025-05-26 18:05:58 +07:00
parent e8c839d493
commit 489f718fec
3 changed files with 61 additions and 41 deletions

View File

@ -29,8 +29,8 @@ const isBrowser = typeof window !== 'undefined' && typeof document !== 'undefine
console.log('Инициализация системы безопасности устройств...'); console.log('Инициализация системы безопасности устройств...');
await deviceSecurityService.initialize(); await deviceSecurityService.initialize();
// Подписываемся на события блокировки устройства // Исправлено: Используем правильный метод onDeviceBlock вместо onDeviceBlocked
deviceSecurityService.onDeviceBlocked(handleDeviceBlocked); deviceSecurityService.onDeviceBlock(handleDeviceBlocked);
console.log('Система безопасности устройств инициализирована'); console.log('Система безопасности устройств инициализирована');

View File

@ -18,6 +18,7 @@ class DeviceSecurityService {
this.suspiciousActivities = []; this.suspiciousActivities = [];
this.lastFingerprintCheck = null; this.lastFingerprintCheck = null;
this.checkInterval = null; this.checkInterval = null;
this.blockCallbacks = []; // Добавляем массив для хранения колбэков блокировки
// Настройки мониторинга // Настройки мониторинга
this.config = { 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(); 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); this.showBlockedNotification(blockInfo);

View File

@ -175,54 +175,51 @@ class DeviceFingerprint {
return new Promise((resolve) => { return new Promise((resolve) => {
try { try {
// Если AudioContext недоступен, просто пропускаем этот шаг
if (!window.AudioContext && !window.webkitAudioContext) { if (!window.AudioContext && !window.webkitAudioContext) {
console.warn('[DeviceFingerprint] AudioContext не поддерживается');
this.components.set('audio', 'not-available');
resolve(); resolve();
return; return;
} }
const AudioContext = window.AudioContext || window.webkitAudioContext; // Создаём аудио хэш на основе доступных properties AudioContext
const context = new AudioContext(); // без использования ScriptProcessorNode
const createAudioFingerprintFallback = () => {
const oscillator = context.createOscillator(); try {
const analyser = context.createAnalyser(); const AudioContext = window.AudioContext || window.webkitAudioContext;
const gainNode = context.createGain(); const context = new AudioContext();
const scriptProcessor = context.createScriptProcessor(4096, 1, 1);
const audioProps = {
oscillator.type = 'triangle'; sampleRate: context.sampleRate,
oscillator.frequency.value = 10000; state: context.state,
baseLatency: context.baseLatency || 0,
gainNode.gain.value = 0; outputLatency: context.outputLatency || 0
};
oscillator.connect(analyser);
analyser.connect(scriptProcessor); // Преобразуем эти свойства в хэш
scriptProcessor.connect(gainNode); const audioHash = this.simpleHash(JSON.stringify(audioProps));
gainNode.connect(context.destination); this.components.set('audio', audioHash);
scriptProcessor.onaudioprocess = async (event) => { // Закрываем context
const bins = new Float32Array(analyser.frequencyBinCount); if (context.state !== 'closed') {
analyser.getFloatFrequencyData(bins); context.close();
}
const audioHash = await this.hashString(bins.slice(0, 50).join(','));
this.components.set('audio', audioHash); resolve();
} catch (e) {
oscillator.disconnect(); console.warn('[DeviceFingerprint] Ошибка в audio fingerprint fallback:', e);
context.close(); this.components.set('audio', 'error');
resolve(); resolve();
}
}; };
oscillator.start(); // Используем безопасный fallback вместо устаревшего ScriptProcessor
// и AudioWorklet (который требует отдельного файла и https)
// Таймаут на случай проблем createAudioFingerprintFallback();
setTimeout(() => {
try {
oscillator.disconnect();
context.close();
} catch (e) {}
resolve();
}, 1000);
} catch (e) { } catch (e) {
console.warn('[DeviceFingerprint] Не удалось создать audio fingerprint:', e); console.warn('[DeviceFingerprint] Не удалось создать audio fingerprint:', e);
this.components.set('audio', 'error');
resolve(); resolve();
} }
}); });