Ressources Séla

Nos livres blancs

Guides pratiques et ressources pour renforcer votre cybersécurité et optimiser votre infrastructure IT.

TPE/PME: Sécuriser les mots de passe
en 2025

24 novembre 2025

Livre blanc 2025 : Sécuriser facilement les mots de passe en TPE/PME

Un guide pratique qui rassemble les bonnes pratiques essentielles pour créer et gérer des mots de passe fiables en 2025, avec une approche simple, concrète et immédiatement applicable dans le quotidien d'une petite ou moyenne entreprise.

Cybersécurité Mots de passe Livre blanc Sécurité
Télécharger le livre blanc (PDF)
// Vérifier si on est en mode file:// if (window.location.protocol === 'file:') { throw new Error('Les fichiers markdown ne peuvent pas être chargés avec file://. Utilisez un serveur HTTP (ex: python3 -m http.server 8000)'); } const response = await fetch(manifestItem.path); if (!response.ok) { throw new Error(`HTTP ${response.status}: Impossible de charger ${manifestItem.path}. Vérifiez que le fichier existe et que vous utilisez un serveur HTTP.`); } const raw = await response.text(); if (!raw || raw.trim().length === 0) { throw new Error(`Le fichier ${manifestItem.path} est vide.`); } const parsed = parseFrontMatter(raw); return { ...manifestItem, ...parsed }; } catch (error) { console.error(`Erreur lors du chargement de ${manifestItem.path}:`, error); throw error; } } function parseFrontMatter(markdownText) { const frontMatterRegex = /^---\s*([\s\S]*?)\s*---\s*/; const match = markdownText.match(frontMatterRegex); let metadata = {}; let content = markdownText; if (match) { const frontMatter = match[1]; content = markdownText.slice(match[0].length); frontMatter.split('\n').forEach(line => { const trimmedLine = line.trim(); if (!trimmedLine) return; const colonIndex = trimmedLine.indexOf(':'); if (colonIndex === -1) return; const key = trimmedLine.substring(0, colonIndex).trim(); let value = trimmedLine.substring(colonIndex + 1).trim(); // Enlever les guillemets au début et à la fin if ((value.startsWith('"') && value.endsWith('"')) || (value.startsWith("'") && value.endsWith("'"))) { value = value.slice(1, -1); } // Gérer les tableaux if (value.startsWith('[') && value.endsWith(']')) { try { metadata[key] = JSON.parse(value); } catch (error) { // Si le parsing échoue, essayer de parser manuellement const items = value.slice(1, -1).split(',').map(item => { const cleaned = item.trim().replace(/^["']|["']$/g, ''); return cleaned; }); metadata[key] = items; } } else { metadata[key] = value; } }); } return { metadata, content }; } function buildArticleCard(article) { const { metadata } = article; const date = metadata.date ? new Date(metadata.date).toLocaleDateString('fr-FR', { day: '2-digit', month: 'long', year: 'numeric' }) : 'Date à venir'; const tags = Array.isArray(metadata.tags) ? metadata.tags : []; const excerpt = metadata.excerpt || article.content.slice(0, 220) + '…'; return `
${metadata.cover ? `${metadata.title || ''}` : 'Séla'}

${date}

${metadata.title || 'Article sans titre'}

${excerpt}

${tags.map(tag => `${tag}`).join('')}
`; } const articleCache = new Map(); async function renderArticles() { const grid = document.getElementById('articles-grid'); const emptyState = document.getElementById('articles-empty-state'); if (!grid) return; // Debug: vérifier le protocole console.log('Protocole détecté:', window.location.protocol); console.log('URL complète:', window.location.href); grid.innerHTML = ` ${Array.from({ length: 2 }).map(() => `
`).join('')} `; try { const results = await Promise.allSettled(articlesManifest.map(loadMarkdownArticle)); const articles = []; const errors = []; results.forEach((result, index) => { if (result.status === 'fulfilled') { articles.push(result.value); } else { const manifestItem = articlesManifest[index]; errors.push({ path: manifestItem.path, error: result.reason }); console.error(`Erreur pour ${manifestItem.path}:`, result.reason); } }); if (articles.length > 0) { grid.innerHTML = articles.map(article => { articleCache.set(article.id, article); return buildArticleCard(article); }).join(''); grid.classList.remove('hidden'); emptyState.classList.add('hidden'); attachArticleEvents(); // Afficher un avertissement si certains articles ont échoué if (errors.length > 0) { console.warn(`${errors.length} article(s) n'ont pas pu être chargés:`, errors); } } else { // Aucun article chargé - afficher les erreurs const isFileProtocol = window.location.protocol === 'file:'; grid.innerHTML = `

❌ Impossible de charger les articles

${errors.length > 0 ? `

${errors.length} article(s) n'ont pas pu être chargés.

` : ''} ${isFileProtocol ? `

💡 Solution : Utilisez un serveur HTTP

Les fichiers markdown ne peuvent pas être chargés directement depuis le navigateur (file://) à cause des restrictions de sécurité.

Dans un terminal, exécutez :

cd /Users/alex/Documents/Projet/SelaV1
python3 -m http.server 8000

Puis ouvrez dans votre navigateur :

http://localhost:8000/noslivresblanc.html
` : `

Vérifiez que les fichiers markdown existent dans le dossier actualites/articles/

`}
`; grid.classList.remove('hidden'); emptyState.classList.add('hidden'); } } catch (error) { console.error('Erreur chargement articles', error); const isFileProtocol = window.location.protocol === 'file:'; grid.innerHTML = `

Erreur lors du chargement des articles

${error.message || 'Vérifiez les chemins markdown.'}

${isFileProtocol ? `

💡 Solution : Utilisez un serveur HTTP

Les fichiers markdown ne peuvent pas être chargés directement depuis le navigateur (file://).

cd /Users/alex/Documents/Projet/SelaV1
python3 -m http.server 8000

Puis ouvrez : http://localhost:8000/noslivresblanc.html

` : ''}
`; } } function attachArticleEvents() { const buttons = document.querySelectorAll('.article-read-more'); buttons.forEach(btn => { btn.addEventListener('click', (event) => { const id = event.currentTarget.dataset.articleId; openArticleModal(id); }); }); } function openArticleModal(articleId) { const modal = document.getElementById('article-modal'); const title = document.getElementById('article-modal-title'); const meta = document.getElementById('article-modal-meta'); const contentEl = document.getElementById('article-modal-content'); const article = articleCache.get(articleId); if (!article || !modal) return; const { metadata, content } = article; title.textContent = metadata.title || 'Article'; const date = metadata.date ? new Date(metadata.date).toLocaleDateString('fr-FR', { day: '2-digit', month: 'long', year: 'numeric' }) : ''; meta.textContent = `${metadata.author || 'Séla'} • ${date}`; contentEl.innerHTML = marked.parse(content); modal.classList.remove('hidden'); modal.classList.add('flex'); document.body.style.overflow = 'hidden'; } function closeArticleModal() { const modal = document.getElementById('article-modal'); if (!modal) return; modal.classList.add('hidden'); modal.classList.remove('flex'); document.body.style.overflow = ''; } document.addEventListener('DOMContentLoaded', () => { renderArticles(); const modal = document.getElementById('article-modal'); const closeBtn = document.getElementById('article-modal-close'); if (closeBtn) closeBtn.addEventListener('click', closeArticleModal); if (modal) { modal.addEventListener('click', (e) => { if (e.target === modal) closeArticleModal(); }); } document.addEventListener('keydown', (e) => { if (e.key === 'Escape') closeArticleModal(); }); });