fixes: favoritos y mas cosas
Signed-off-by: Omar Sánchez Pizarro <omar.sanchez@pistacero.net>
This commit is contained in:
165
web/backend/utils/fingerprint.js
Normal file
165
web/backend/utils/fingerprint.js
Normal file
@@ -0,0 +1,165 @@
|
||||
import crypto from 'crypto';
|
||||
|
||||
/**
|
||||
* Genera un fingerprint del dispositivo basado en headers HTTP
|
||||
* @param {Object} req - Request object de Express
|
||||
* @returns {Object} Objeto con fingerprint hash y metadata del dispositivo
|
||||
*/
|
||||
export function generateDeviceFingerprint(req) {
|
||||
// Extraer información del dispositivo desde headers
|
||||
const userAgent = req.headers['user-agent'] || '';
|
||||
const acceptLanguage = req.headers['accept-language'] || '';
|
||||
const acceptEncoding = req.headers['accept-encoding'] || '';
|
||||
const accept = req.headers['accept'] || '';
|
||||
const connection = req.headers['connection'] || '';
|
||||
const upgradeInsecureRequests = req.headers['upgrade-insecure-requests'] || '';
|
||||
|
||||
// IP del cliente (considerando proxies)
|
||||
const ip = req.ip ||
|
||||
req.headers['x-forwarded-for']?.split(',')[0]?.trim() ||
|
||||
req.headers['x-real-ip'] ||
|
||||
req.connection?.remoteAddress ||
|
||||
'unknown';
|
||||
|
||||
// Crear string combinado para el hash
|
||||
const fingerprintString = [
|
||||
userAgent,
|
||||
acceptLanguage,
|
||||
acceptEncoding,
|
||||
accept,
|
||||
connection,
|
||||
upgradeInsecureRequests,
|
||||
ip
|
||||
].join('|');
|
||||
|
||||
// Generar hash SHA-256
|
||||
const fingerprintHash = crypto
|
||||
.createHash('sha256')
|
||||
.update(fingerprintString)
|
||||
.digest('hex');
|
||||
|
||||
// Extraer información legible del User-Agent
|
||||
const deviceInfo = parseUserAgent(userAgent);
|
||||
|
||||
return {
|
||||
fingerprint: fingerprintHash,
|
||||
deviceInfo: {
|
||||
...deviceInfo,
|
||||
ip: ip,
|
||||
userAgent: userAgent.substring(0, 200), // Limitar longitud
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Parsea el User-Agent para extraer información legible
|
||||
* @param {string} userAgent - User-Agent string
|
||||
* @returns {Object} Información del dispositivo
|
||||
*/
|
||||
function parseUserAgent(userAgent) {
|
||||
if (!userAgent) {
|
||||
return {
|
||||
browser: 'Unknown',
|
||||
browserVersion: '',
|
||||
os: 'Unknown',
|
||||
osVersion: '',
|
||||
device: 'Unknown',
|
||||
};
|
||||
}
|
||||
|
||||
const ua = userAgent.toLowerCase();
|
||||
|
||||
// Detectar navegador
|
||||
let browser = 'Unknown';
|
||||
let browserVersion = '';
|
||||
|
||||
if (ua.includes('chrome') && !ua.includes('edg') && !ua.includes('opr')) {
|
||||
browser = 'Chrome';
|
||||
const match = ua.match(/chrome\/([\d.]+)/);
|
||||
browserVersion = match ? match[1] : '';
|
||||
} else if (ua.includes('firefox')) {
|
||||
browser = 'Firefox';
|
||||
const match = ua.match(/firefox\/([\d.]+)/);
|
||||
browserVersion = match ? match[1] : '';
|
||||
} else if (ua.includes('safari') && !ua.includes('chrome')) {
|
||||
browser = 'Safari';
|
||||
const match = ua.match(/version\/([\d.]+)/);
|
||||
browserVersion = match ? match[1] : '';
|
||||
} else if (ua.includes('edg')) {
|
||||
browser = 'Edge';
|
||||
const match = ua.match(/edg\/([\d.]+)/);
|
||||
browserVersion = match ? match[1] : '';
|
||||
} else if (ua.includes('opr')) {
|
||||
browser = 'Opera';
|
||||
const match = ua.match(/opr\/([\d.]+)/);
|
||||
browserVersion = match ? match[1] : '';
|
||||
}
|
||||
|
||||
// Detectar sistema operativo
|
||||
let os = 'Unknown';
|
||||
let osVersion = '';
|
||||
|
||||
if (ua.includes('windows')) {
|
||||
os = 'Windows';
|
||||
if (ua.includes('windows nt 10')) osVersion = '10/11';
|
||||
else if (ua.includes('windows nt 6.3')) osVersion = '8.1';
|
||||
else if (ua.includes('windows nt 6.2')) osVersion = '8';
|
||||
else if (ua.includes('windows nt 6.1')) osVersion = '7';
|
||||
} else if (ua.includes('mac os x') || ua.includes('macintosh')) {
|
||||
os = 'macOS';
|
||||
const match = ua.match(/mac os x ([\d_]+)/);
|
||||
osVersion = match ? match[1].replace(/_/g, '.') : '';
|
||||
} else if (ua.includes('linux')) {
|
||||
os = 'Linux';
|
||||
} else if (ua.includes('android')) {
|
||||
os = 'Android';
|
||||
const match = ua.match(/android ([\d.]+)/);
|
||||
osVersion = match ? match[1] : '';
|
||||
} else if (ua.includes('ios') || ua.includes('iphone') || ua.includes('ipad')) {
|
||||
os = 'iOS';
|
||||
const match = ua.match(/os ([\d_]+)/);
|
||||
osVersion = match ? match[1].replace(/_/g, '.') : '';
|
||||
}
|
||||
|
||||
// Detectar tipo de dispositivo
|
||||
let device = 'Desktop';
|
||||
if (ua.includes('mobile') || ua.includes('android') || ua.includes('iphone')) {
|
||||
device = 'Mobile';
|
||||
} else if (ua.includes('tablet') || ua.includes('ipad')) {
|
||||
device = 'Tablet';
|
||||
}
|
||||
|
||||
return {
|
||||
browser,
|
||||
browserVersion,
|
||||
os,
|
||||
osVersion,
|
||||
device,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Genera un fingerprint desde el frontend (cuando se envía desde el cliente)
|
||||
* @param {string} fingerprintHash - Hash del fingerprint generado en el cliente
|
||||
* @param {Object} deviceInfo - Información del dispositivo del cliente
|
||||
* @param {Object} req - Request object de Express
|
||||
* @returns {Object} Objeto con fingerprint y metadata combinada
|
||||
*/
|
||||
export function combineFingerprint(fingerprintHash, deviceInfo, req) {
|
||||
const serverFingerprint = generateDeviceFingerprint(req);
|
||||
|
||||
// Si el cliente envió un fingerprint, combinarlo con el del servidor
|
||||
// Esto permite usar librerías avanzadas del cliente pero validar con servidor
|
||||
const combinedFingerprint = fingerprintHash
|
||||
? crypto.createHash('sha256').update(fingerprintHash + serverFingerprint.fingerprint).digest('hex')
|
||||
: serverFingerprint.fingerprint;
|
||||
|
||||
return {
|
||||
fingerprint: combinedFingerprint,
|
||||
deviceInfo: {
|
||||
...serverFingerprint.deviceInfo,
|
||||
...deviceInfo, // El del cliente tiene prioridad si existe
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user