Initial commit
This commit is contained in:
150
utils/secureStorage.ts
Normal file
150
utils/secureStorage.ts
Normal file
@@ -0,0 +1,150 @@
|
||||
/**
|
||||
* Utilitaire de stockage sécurisé pour BTP Xpress
|
||||
* Gestion des tokens et données sensibles
|
||||
*/
|
||||
|
||||
export interface StorageItem {
|
||||
value: any;
|
||||
timestamp: number;
|
||||
expiry?: number;
|
||||
}
|
||||
|
||||
export class SecureStorage {
|
||||
private static readonly PREFIX = 'btpxpress_';
|
||||
|
||||
/**
|
||||
* Stocke une valeur de manière sécurisée
|
||||
*/
|
||||
static set(key: string, value: any, expiryMinutes?: number): void {
|
||||
try {
|
||||
const item: StorageItem = {
|
||||
value,
|
||||
timestamp: Date.now(),
|
||||
expiry: expiryMinutes ? Date.now() + (expiryMinutes * 60 * 1000) : undefined
|
||||
};
|
||||
|
||||
const storageKey = this.PREFIX + key;
|
||||
const encrypted = this.encrypt(JSON.stringify(item));
|
||||
|
||||
// Utiliser sessionStorage par défaut pour plus de sécurité
|
||||
sessionStorage.setItem(storageKey, encrypted);
|
||||
} catch (error) {
|
||||
console.error('Erreur lors du stockage sécurisé:', error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Récupère une valeur stockée
|
||||
*/
|
||||
static get(key: string): any {
|
||||
try {
|
||||
const storageKey = this.PREFIX + key;
|
||||
const encrypted = sessionStorage.getItem(storageKey) || localStorage.getItem(storageKey);
|
||||
|
||||
if (!encrypted) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const decrypted = this.decrypt(encrypted);
|
||||
const item: StorageItem = JSON.parse(decrypted);
|
||||
|
||||
// Vérifier l'expiration
|
||||
if (item.expiry && Date.now() > item.expiry) {
|
||||
this.remove(key);
|
||||
return null;
|
||||
}
|
||||
|
||||
return item.value;
|
||||
} catch (error) {
|
||||
console.error('Erreur lors de la récupération sécurisée:', error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Supprime une valeur stockée
|
||||
*/
|
||||
static remove(key: string): void {
|
||||
try {
|
||||
const storageKey = this.PREFIX + key;
|
||||
sessionStorage.removeItem(storageKey);
|
||||
localStorage.removeItem(storageKey);
|
||||
} catch (error) {
|
||||
console.error('Erreur lors de la suppression sécurisée:', error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Vide tout le stockage sécurisé
|
||||
*/
|
||||
static clearAll(): void {
|
||||
try {
|
||||
// Nettoyer sessionStorage
|
||||
Object.keys(sessionStorage).forEach(key => {
|
||||
if (key.startsWith(this.PREFIX)) {
|
||||
sessionStorage.removeItem(key);
|
||||
}
|
||||
});
|
||||
|
||||
// Nettoyer localStorage
|
||||
Object.keys(localStorage).forEach(key => {
|
||||
if (key.startsWith(this.PREFIX)) {
|
||||
localStorage.removeItem(key);
|
||||
}
|
||||
});
|
||||
|
||||
// Nettoyer aussi les anciens tokens
|
||||
sessionStorage.removeItem('auth_token');
|
||||
localStorage.removeItem('auth_token');
|
||||
localStorage.removeItem('token');
|
||||
localStorage.removeItem('user');
|
||||
} catch (error) {
|
||||
console.error('Erreur lors du nettoyage sécurisé:', error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si une clé existe et n'est pas expirée
|
||||
*/
|
||||
static exists(key: string): boolean {
|
||||
return this.get(key) !== null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Chiffrement simple (Base64 + rotation)
|
||||
* Note: Pour un vrai projet, utiliser une vraie bibliothèque de chiffrement
|
||||
*/
|
||||
private static encrypt(data: string): string {
|
||||
try {
|
||||
// Chiffrement simple avec Base64 et rotation de caractères
|
||||
const rotated = data.split('').map(char =>
|
||||
String.fromCharCode(char.charCodeAt(0) + 3)
|
||||
).join('');
|
||||
|
||||
return btoa(rotated);
|
||||
} catch (error) {
|
||||
console.error('Erreur de chiffrement:', error);
|
||||
return btoa(data); // Fallback vers Base64 simple
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Déchiffrement simple
|
||||
*/
|
||||
private static decrypt(encrypted: string): string {
|
||||
try {
|
||||
const decoded = atob(encrypted);
|
||||
|
||||
// Dérotation des caractères
|
||||
return decoded.split('').map(char =>
|
||||
String.fromCharCode(char.charCodeAt(0) - 3)
|
||||
).join('');
|
||||
} catch (error) {
|
||||
console.error('Erreur de déchiffrement:', error);
|
||||
return atob(encrypted); // Fallback vers Base64 simple
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Export par défaut pour compatibilité
|
||||
export default SecureStorage;
|
||||
Reference in New Issue
Block a user