- Task #6: WebSocket /ws/dashboard + Kafka events (5 topics) * Backend: KafkaEventProducer, KafkaEventConsumer * Mobile: WebSocketService (reconnection, heartbeat, typed events) * DashboardBloc: Auto-refresh depuis WebSocket events - Finance Workflow: approbations + budgets (backend + mobile) * Backend: entities, services, resources, migrations Flyway V6 * Mobile: features finance_workflow complète avec BLoC - Corrections DI: interfaces IRepository partout * IProfileRepository, IOrganizationRepository, IMembreRepository * GetIt configuré avec @injectable - Spec-Kit: constitution + templates mis à jour * .specify/memory/constitution.md enrichie * Templates agent, plan, spec, tasks, checklist - Nettoyage: fichiers temporaires supprimés Signed-off-by: lions dev Team
13 KiB
Implémentation de la Sécurisation Granulaire des Pages
Date: 2026-03-02 Système: UnionFlow Client Web (Quarkus + PrimeFaces)
Résumé Exécutif
Implémentation d'un système de sécurisation centralisé DRY/WOU pour contrôler l'accès aux 100+ pages de l'application basé sur les rôles utilisateurs.
Principes Appliqués
✅ DRY (Don't Repeat Yourself) : Une seule implémentation de la logique de sécurité ✅ WOU (Write Once Use) : Composant réutilisable pour toutes les pages ✅ Défense en profondeur : Sécurité à 3 niveaux (page, bean, API) ✅ Least Privilege : Accès minimum nécessaire par rôle ✅ Audit Trail : Logging automatique des refus d'accès
Architecture de Sécurité
1. Bean Centralisé de Sécurité
Fichier : PageSecurityBean.java
@Named("pageSecurityBean")
@ApplicationScoped
public class PageSecurityBean {
/**
* Vérifie l'accès et redirige si refusé
*/
public boolean checkAccessOrRedirect(String allowedRoles) {
// Logique centralisée de vérification
// Redirection automatique vers access-denied
// Logging des tentatives d'accès non autorisées
}
// Méthodes helper pour vérifications rapides
public boolean canManageMembers();
public boolean canManageFinances();
public boolean canManageEvents();
public boolean canManageSocialAid();
public boolean isSimpleMember();
}
Avantages :
- ✅ Une seule source de vérité pour la logique de sécurité
- ✅ Facile à maintenir et à tester
- ✅ Logging centralisé des accès refusés
- ✅ Réutilisable dans les beans et les pages
2. Composant Facelet Réutilisable
Fichier : /templates/components/security/page-access-control.xhtml
<ui:composition>
<cc:interface>
<cc:attribute name="allowedRoles" type="java.lang.String" />
</cc:interface>
<cc:implementation>
<ui:fragment rendered="#{not pageSecurityBean.checkAccessOrRedirect(cc.attrs.allowedRoles)}" />
</cc:implementation>
</ui:composition>
Usage dans une page :
<ui:composition template="/templates/main-template.xhtml">
<!-- Sécurisation de la page -->
<ui:include src="/templates/components/security/page-access-control.xhtml">
<ui:param name="allowedRoles" value="TRESORIER,ADMIN" />
</ui:include>
<ui:define name="content">
<!-- Contenu de la page -->
</ui:define>
</ui:composition>
3. Matrice de Permissions
Fichier : docs/PERMISSIONS_MATRIX.md
Matrice complète documentant les 100+ pages et leurs rôles autorisés :
- Pages Super Admin (5 pages)
- Pages Admin Organisation (9 pages)
- Pages Gestion Membres (6 pages)
- Pages Gestion Financière (11 pages)
- Pages Gestion Événements (15 pages)
- Pages Gestion Aides (7 pages)
- Pages Adhésions (9 pages)
- Pages Rapports (9 pages)
- Pages Personnelles (10 pages)
- Pages Aide/Support (9 pages)
- Pages Communication, Documents, Utilitaires (6 pages)
- Pages Publiques (2 pages)
Hiérarchie des Rôles
SUPER_ADMIN (accès total)
└─ ADMIN_ORGANISATION (gestion organisation)
├─ TRESORIER (finances)
├─ SECRETAIRE (administratif)
├─ RESPONSABLE_SOCIAL (aides sociales)
├─ RESPONSABLE_EVENEMENTS (événements)
├─ RESPONSABLE_CREDIT (épargne/crédit)
└─ MEMBRE_BUREAU (bureau exécutif)
└─ MEMBRE_ACTIF (membre avec cotisations à jour)
└─ MEMBRE_SIMPLE (membre avec accès limité)
Règle d'héritage : Les rôles supérieurs héritent automatiquement des permissions des rôles inférieurs.
Exemples de Sécurisation
Page de Gestion Financière
<!-- /secure/finance/tresorerie.xhtml -->
<ui:composition template="/templates/main-template.xhtml">
<ui:include src="/templates/components/security/page-access-control.xhtml">
<ui:param name="allowedRoles" value="TRESORIER,ADMIN" />
</ui:include>
<!-- Accessible uniquement par TRESORIER, ADMIN_ORGANISATION, SUPER_ADMIN -->
</ui:composition>
Page Personnelle (Tous)
<!-- /secure/personnel/profil.xhtml -->
<ui:composition template="/templates/main-template.xhtml">
<ui:include src="/templates/components/security/page-access-control.xhtml">
<ui:param name="allowedRoles" value="ALL" />
</ui:include>
<!-- Accessible par tous les utilisateurs authentifiés -->
</ui:composition>
Page Multi-Rôles
<!-- /secure/membre/recherche.xhtml -->
<ui:composition template="/templates/main-template.xhtml">
<ui:include src="/templates/components/security/page-access-control.xhtml">
<ui:param name="allowedRoles" value="SECRETAIRE,TRESORIER,RESPONSABLE_SOCIAL,RESPONSABLE_EVENEMENTS,ADMIN" />
</ui:include>
<!-- Accessible par plusieurs rôles administratifs -->
</ui:composition>
Script d'Automatisation
Fichier : scripts/apply-page-security.ps1
Script PowerShell pour appliquer automatiquement la sécurisation à toutes les pages existantes :
# Usage
.\apply-page-security.ps1
# Résultat
# - Lit la matrice de permissions
# - Parcourt toutes les pages XHTML
# - Insère le composant de sécurité avec les rôles appropriés
# - Log : pages sécurisées, ignorées, erreurs
Fonctionnalités :
- ✅ Détection automatique des pages déjà sécurisées
- ✅ Insertion intelligente du composant de sécurité
- ✅ Préservation de l'encodage UTF-8
- ✅ Rapport détaillé (succès, skip, erreurs)
Pages Déjà Sécurisées
Dashboard Principal
- Fichier :
/secure/dashboard.xhtml - Méthode : Redirection dans
DashboardBean.java @PostConstruct - Logique : Les MEMBRE_ACTIF (sans autre rôle) sont redirigés vers
/dashboard-membre.xhtml
Dashboard Membre Personnel
- Fichier :
/secure/dashboard-membre.xhtml - Rôles : Tous les membres authentifiés
- Spécificité : Affiche uniquement les données personnelles du membre connecté
Pages Critiques Sécurisées Manuellement
- ✅
/secure/membre/inscription.xhtml→SECRETAIRE,ADMIN - ✅
/secure/finance/tresorerie.xhtml→TRESORIER,ADMIN
Niveaux de Sécurité (Défense en Profondeur)
Niveau 1 : Page XHTML
<ui:include src="/templates/components/security/page-access-control.xhtml">
<ui:param name="allowedRoles" value="TRESORIER,ADMIN" />
</ui:include>
→ Avantage : Interception immédiate, redirection rapide
Niveau 2 : Bean Backing
@PostConstruct
public void init() {
if (!pageSecurityBean.canManageFinances()) {
// Redirection programmée
FacesContext.getCurrentInstance().getExternalContext()
.redirect("/pages/secure/access-denied.xhtml");
}
}
→ Avantage : Contrôle métier supplémentaire
Niveau 3 : API REST Backend
@GET
@Path("/tresorerie")
@RolesAllowed({"TRESORIER", "ADMIN_ORGANISATION", "SUPER_ADMIN"})
public Response getTresorerie() {
// Endpoint sécurisé côté serveur
}
→ Avantage : Protection ultime contre les appels API directs
Comportement en Cas de Refus d'Accès
- Détection :
PageSecurityBean.checkAccessOrRedirect()vérifie les rôles - Logging : Enregistrement du refus avec username et page demandée
[WARN] Accès refusé pour l'utilisateur john.doe@example.com à une page nécessitant les rôles: TRESORIER,ADMIN - Redirection : Envoi automatique vers
/secure/access-denied.xhtml - Message : Page d'erreur affichant le contexte du refus
Méthodes Helper Disponibles
Dans PageSecurityBean
// Vérifications de capacités
pageSecurityBean.canManageMembers() // SECRETAIRE, ADMIN
pageSecurityBean.canManageFinances() // TRESORIER, ADMIN
pageSecurityBean.canManageEvents() // RESPONSABLE_EVENEMENTS, SECRETAIRE, ADMIN
pageSecurityBean.canManageSocialAid() // RESPONSABLE_SOCIAL, ADMIN
pageSecurityBean.canViewFinancialReports() // TRESORIER, SECRETAIRE, ADMIN
pageSecurityBean.canExportData() // TRESORIER, SECRETAIRE, ADMIN
// Vérification de rôle simple
pageSecurityBean.isSimpleMember() // MEMBRE_ACTIF uniquement (pas admin)
Dans MenuBean
// Vérifications de rôles individuels
menuBean.isSuperAdmin()
menuBean.isAdminOrganisation()
menuBean.isTresorier()
menuBean.isSecretaire()
menuBean.isResponsableSocial()
menuBean.isResponsableEvenements()
menuBean.isResponsableCredit()
menuBean.isMembreBureau()
menuBean.isMembreActif()
menuBean.isMembreSimple()
Tests de Sécurité
Tests Unitaires Requis
@QuarkusTest
public class PageSecurityBeanTest {
@Test
public void testTresorierCanAccessFinancePage() {
// Given: User with TRESORIER role
// When: checkAccessOrRedirect("TRESORIER,ADMIN")
// Then: Returns true
}
@Test
public void testMembreActifCannotAccessAdminPage() {
// Given: User with MEMBRE_ACTIF only
// When: checkAccessOrRedirect("ADMIN")
// Then: Returns false + redirects
}
}
Tests d'Intégration
@QuarkusTest
public class PageAccessIntegrationTest {
@Test
@TestSecurity(user = "tresorier", roles = {"TRESORIER"})
public void testTresoreriePageAccessible() {
// Accès page /secure/finance/tresorerie.xhtml
// Vérifier HTTP 200
}
@Test
@TestSecurity(user = "membre", roles = {"MEMBRE_ACTIF"})
public void testTresoreriePageDenied() {
// Accès page /secure/finance/tresorerie.xhtml
// Vérifier redirection vers access-denied
}
}
Maintenance et Évolution
Ajout d'une Nouvelle Page
- Créer la page XHTML dans le répertoire approprié
- Déterminer les rôles autorisés selon la matrice de permissions
- Ajouter le composant de sécurité :
<ui:include src="/templates/components/security/page-access-control.xhtml"> <ui:param name="allowedRoles" value="VOTRE_ROLE,ADMIN" /> </ui:include> - Mettre à jour
PERMISSIONS_MATRIX.md - Mettre à jour
apply-page-security.ps1si nécessaire
Ajout d'un Nouveau Rôle
- Ajouter le rôle dans Keycloak (realm configuration)
- Mettre à jour
MenuBean.javaavec la méthodeisNouveauRole() - Mettre à jour
PageSecurityBean.hasRole()avec le nouveau cas - Documenter dans
PERMISSIONS_MATRIX.md - Réviser les pages existantes pour voir si le nouveau rôle doit y accéder
Métriques de Sécurité
Couverture Actuelle
- Pages totales : 100+
- Pages sécurisées : 2 (manuellement) + 98 (via script)
- Couverture : 100% (après exécution du script)
Rôles par Catégorie de Page
| Catégorie | Rôles Principaux | Nombre de Pages |
|---|---|---|
| Super Admin | SUPER_ADMIN | 5 |
| Admin Organisation | ADMIN | 9 |
| Finances | TRESORIER | 11 |
| Membres | SECRETAIRE | 6 |
| Événements | RESPONSABLE_EVENEMENTS | 15 |
| Aides Sociales | RESPONSABLE_SOCIAL | 7 |
| Personnel | ALL | 20 |
| Publiques | Aucune auth | 2 |
Recommandations
Court Terme (Priorité P1)
- ✅ Exécuter le script
apply-page-security.ps1pour sécuriser toutes les pages - ⏳ Tester les redirections pour chaque rôle
- ⏳ Implémenter les tests unitaires pour
PageSecurityBean - ⏳ Valider la matrice de permissions avec les métiers
Moyen Terme (Priorité P2)
- ⏳ Créer un dashboard de monitoring des accès refusés
- ⏳ Implémenter l'audit trail détaillé des accès
- ⏳ Ajouter des tests d'intégration E2E
- ⏳ Documenter les cas d'usage par rôle
Long Terme (Priorité P3)
- ⏳ Permissions granulaires par entité (ex: voir uniquement son organisation)
- ⏳ Délégation de permissions temporaires
- ⏳ Gestion des permissions via interface admin
- ⏳ Revue périodique des permissions (trimestrielle)
Conformité et Standards
Standards Appliqués
- ✅ OWASP Top 10 : Protection contre les failles de contrôle d'accès
- ✅ Principe du moindre privilège : Accès minimum nécessaire
- ✅ Séparation des préoccupations : Sécurité séparée de la logique métier
- ✅ Audit logging : Traçabilité des accès
Checklist de Conformité
- Toutes les pages ont une politique de sécurité explicite
- Les rôles sont documentés et hiérarchisés
- Les refus d'accès sont loggés
- Les utilisateurs sont redirigés (pas d'erreur 403 brutale)
- Tests de sécurité automatisés (TODO)
- Revue de code sécurité (TODO)
- Scan de vulnérabilités (TODO)
Contact et Support
Équipe : UnionFlow Security Team
Documentation : docs/PERMISSIONS_MATRIX.md
Code : PageSecurityBean.java, page-access-control.xhtml
Script : scripts/apply-page-security.ps1
Questions : Contacter l'architecte technique