IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Spring Java Discussion :

Problème critique de sécurité avec les Sessions en couple JSF+Spring


Sujet :

Spring Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre très actif Avatar de bruneltouopi
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2010
    Messages
    308
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Ile Maurice

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2010
    Messages : 308
    Par défaut Problème critique de sécurité avec les Sessions en couple JSF+Spring
    Bonjour,
    Les informations sont partagées entre les users
    J'ai utilisé spring+JSF la sécurité utilisateur marchait avant quand l'architecture était EJB-JSF(Spring-JSF) maintenant.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    @Component
    @ManagedBean(name = "connectionController")
    @SessionScoped
    public class ConnectionController implements Serializable {
     FacesContext ctx = FacesContext.getCurrentInstance();
     Personne u = securiteUser.getAuthentification(login,password);
    //verification
    //si OK chargement des sessions user
     ctx.getExternalContext().getSessionMap().put(GlobalFonctions.SESSION_USER, u);
     
      Collection<Menu> menusUser = securiteUser.getMenusForUser(u);
               Map<String, String> mesChemin = new HashMap<>();
                        for (Menu menu : menusUser) {
                            mesChemin.put(menu.getChemin(), menu.getCode());
                        }
    //chargement des menus de securité
    ctx.getExternalContext().getSessionMap().put(GlobalFonctions.MENUS_USER, mesChemin);
     
    }
    J'ai une méthode qui lit ensuite le Map de session ctx.getExternalContext().getSessionMap().get(GlobalFonctions.MENUS_USER);
    Mon souci est que cette variable est partagée aux différents utilisateurs.
    Quelque fois une utilisateur se retrouve avec les privilèges d'un autre.
    je ne sais pas comment cela se passe mais ca se passe.

  2. #2
    Membre émérite
    Avatar de Cafeinoman
    Homme Profil pro
    Couteau suisse d'une PME
    Inscrit en
    Octobre 2012
    Messages
    628
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Couteau suisse d'une PME

    Informations forums :
    Inscription : Octobre 2012
    Messages : 628
    Par défaut
    Je doute que le problème viennent de jsf... Tu peux poster la classe de ta variable securiteUser?

  3. #3
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    Ce code n'est même pas dans une méthode. Je ne vois pas comment ça pourrait ne serait-ce que compiler, encore moins fonctionner. Ils sortent d'où securiteUser, login,password? Elle fait quoi ta méthode getAuthentification? Il ressemble à quoi ton objet Personne? Y a quoi dans ta classe Menu et dans ton getMenusForUser?

  4. #4
    Membre très actif Avatar de bruneltouopi
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2010
    Messages
    308
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Ile Maurice

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2010
    Messages : 308
    Par défaut
    Désolé si je n'ai pas mis les tous les détails mais je les ajouterais graduellement au besoin
    Citation Envoyé par Cafeinoman Voir le message
    Je doute que le problème viennent de jsf... Tu peux poster la classe de ta variable securiteUser?
    Le probleme ne vient pas justement de JSF.La classe securiteUser n'est pas le problème non plus c'est une component Spring dont voici la déclaration

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    @Service
    @Transactional(readOnly=true)
    public class Securite implements ISecurite {
     
    }
    Citation Envoyé par tchize_ Voir le message
    Ce code n'est même pas dans une méthode. Je ne vois pas comment ça pourrait ne serait-ce que compiler, encore moins fonctionner. Ils sortent d'où securiteUser, login,password? Elle fait quoi ta méthode getAuthentification? Il ressemble à quoi ton objet Personne? Y a quoi dans ta classe Menu et dans ton getMenusForUser?
    Tous ces details ne sont pas très important.la classe securiteUser contient la methode getAuthentification
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     public Personne getAuthentification(String login,String pwd) {
     
            String pwdCript=Crypto.sha256(pwd);
            String jpql = "SELECT us FROM Personne us WHERE us.matricule = :mat and us.pwd = :Pwd";
            Map<String, Object> param = new HashMap<>();
            param.put("mat", login);
            param.put("Pwd", pwdCript);
            Personne user = userDao.findEntityByUsingQuery(jpql, param);
            return user;    
        }
    login et password sont les variables saisies par l'utilisateur.Personne et Menu sont des entités.
    Bref ce code etait fonctionnelle jusqu'au moment oû je constate que les variables de ma session connectionController sont partagés.

    J'ai un Listener qui s'exécute sur les phases de jsf avant l'affichage d'une page pour la sécurité declaré
    dans mon fichier faces-config
    <lifecycle>
    <phase-listener>listeners.MonPhaseListener</phase-listener>
    </lifecycle>
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    public class MonPhaseListener extends DelegatingPhaseListenerMulticaster implements ServletContextListener,Serializable{
    
      
         private static final long serialVersionUID = 1L;
      
           public MonPhaseListener() {
        }
    
        @Override
        public void beforePhase(PhaseEvent pe) {
            if (pe.getPhaseId() == PhaseId.RESTORE_VIEW) {
                System.out.println("Nouvelle requête en cours ...");
            }
            System.out.println("avant - " + pe.getPhaseId().toString());
        }
    
        @Override
        public void afterPhase(PhaseEvent pe) {
    //        System.out.println("après - " + pe.getPhaseId().toString());
            if (pe.getPhaseId() == PhaseId.RESTORE_VIEW) {
                System.out.println("Fin d’analyse de la requête.\n");
    
                FacesContext fc = pe.getFacesContext();
               this.redirectPage(fc);
            }
        }
        
        /**
         * Rediriger les pages en verifiant les contraintes de licence et config
         * @param fc 
         */
        public void redirectPage(FacesContext fc){
           String currentPage = fc.getViewRoot().getViewId();
                System.out.println(currentPage);
                //teste que c la page de login
                boolean loginPage = (currentPage.contains("connection.xhtml") || currentPage.contains("licence.xhtml"));
                //teste si c'est une page xhtml
                boolean xhtmlPage = (currentPage.contains(".xhtml"));
               // ConnectionController connectController = null;
                //si c'est une page differente de login
                if (!loginPage && xhtmlPage) {
                    boolean isLogged = false;
                    System.out.println("test con");
               
                     WebApplicationContext ctx = WebApplicationContextUtils
                    .getRequiredWebApplicationContext((ServletContext) FacesContext
                            .getCurrentInstance().getExternalContext().getContext());
            ConnectionController connectController= ctx.getBean(ConnectionController.class);
                       
                    NavigationHandler nh = fc.getApplication().getNavigationHandler();
                    if (connectController != null) {
                        System.out.println("Connection OK");
    /**** LES VARIABLES DE connectController  SONT REINITIALISEES******/
                        isLogged = connectController.isIsLoggedIn();
                        int status = connectController.verifyContrainstBeforeToOpenPage();
    
                        switch (status) {
                           
                            case GlobalFonctions.GO_TO_CONNECT:
                                nh.handleNavigation(fc, null, "client.deconnect");
                                break;
                            case GlobalFonctions.GO_TO_LICENCE:
                                nh.handleNavigation(fc, null, "license");
                                break;
    //                         case GlobalFonctions.GO_TO_CONFIG:
    //                            nh.handleNavigation(fc, null, "configuration");
    //                            break;
                            case GlobalFonctions.GO_TO_PAGE:
                                this.checkSecurePage(currentPage, fc);
                                connectController.afficheLibellePage();
                                break;
                        }
                    } else {
                        System.out.println("Connection NULL");
                        nh.handleNavigation(fc, null, "client.deconnect");
                    }
    
                }  
        }
    
        /**
         * Verifier les contraintes de securite des users s'ils ont acces la page demande
         * @param currentPage
         * @param fc 
         */
        public void checkSecurePage(String currentPage, FacesContext fc) {
            NavigationHandler nh = fc.getApplication().getNavigationHandler();
            //c'est bien mais verifions que c   le menu qui lui appartient
            String[] myDecomposePage = new String[2];
            myDecomposePage = currentPage.split("\\.");
            String chemin = myDecomposePage[0];
            Map<String, String> colMenu = (HashMap<String, String>) fc.getExternalContext().getSessionMap().get(GlobalFonctions.MENUS_USER);
    
            if (colMenu != null && !colMenu.isEmpty()) {
                String page = colMenu.get(chemin);
                System.out.println("ma page=" + page);
    
                fc.getExternalContext().getRequestMap().put("page", page);
    
            //enlevons principal et pagerror
                if (!chemin.equalsIgnoreCase("/licence") && !chemin.equalsIgnoreCase("/principal") && !chemin.equalsIgnoreCase("/errorpage") &&
                        !chemin.equalsIgnoreCase("/profil")) {
                    if (colMenu.containsKey(chemin) == false) {
                        nh.handleNavigation(fc, null, "pageerror");
                    }
                }
            } else {
                System.out.println("Pas de Menus Operationelles");
                nh.handleNavigation(fc, null, "client.deconnect");
            }
    
        }
        
        
        @Override
        public PhaseId getPhaseId() {
            //je prend juste les vues finales
            return PhaseId.RESTORE_VIEW;
        }
    
        @Override
        public void contextInitialized(ServletContextEvent sce) {
         }
    
        @Override
        public void contextDestroyed(ServletContextEvent sce) {
         }
    }
    Après plusieurs recherches voici ce qu'il en ressort
    Qu'il faut remplacer @SessionScoped avec @Scope("session") de Spring
    après cela je me retrouve avec un warning
    09:54:27.714 [http-bio-8080-exec-32] WARN o.s.w.c.r.FacesRequestAttributes - Could not register destruction callback [org.springframework.beans.factory.support.DisposableBeanAdapter@68e89290] for attribute 'connectionController' because FacesRequestAttributes does not support such callbacks
    après quelques recherches j'ai lu qu' il faut ajouter
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     <listener>
        <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
    </listener>
    bref la même erreur persiste.
    Mon veritable souci actuellement se situe au niveau du Listener après la récuperation de la classe connectionController
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    WebApplicationContext ctx = WebApplicationContextUtils
                    .getRequiredWebApplicationContext((ServletContext) FacesContext
                            .getCurrentInstance().getExternalContext().getContext());
            ConnectionController connectController= ctx.getBean(ConnectionController.class);
    Elle ne garde pas les valeurs de la session ce qui est pourtant la cas quand cette classe est déclarée avec @SessionScoped.
    Je rappelle juste que ce code en version J2EE.je recuperais cette classe avec
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
                 ConnectionController connectController = (ConnectionController)FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("connectionController");
    .

    Voici comment la sécurité a été implémenté.
    A-dans la classe ConnectionController de type Session
    1-Login de l'user
    2-Verification des contraintes licence et configurations avec la methode
    verifyContrainstBeforeToOpenPage();
    3-Chargement des menu de l'user depuis la bd pour lui afficher cela.
    4-Redirection vers la page principale

    B-Execution du Listener MonPhaseListener
    ce listener s'execute à chaque ouverture de page ainsi on peut controler si un user execute une page sur le navigateur alors qu'il n'a pas l'acces à cette page dans ses menu
    1-Exécution de la méthode redirectPage(FacesContext)
    on recupere la classe connectionController et on verifie des contraintes
    ICI PROBLEME les Variables se sont initialises comme si c'est une nouvelle instance

    Bon je m'arrète là je suis ouvert aux suggestions s'il y'a une autre facon de faire dans mon cas.
    Merci

  5. #5
    Membre confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2013
    Messages
    36
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2013
    Messages : 36
    Par défaut
    juste cette ligne qui m'intrigue.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    FacesContext ctx = FacesContext.getCurrentInstance();
    C'est juste une piste. Les Bean Spring sont par défaut des singleton. Ici en "SessionScoped" ils y ajoutent un mecanisme de proxy. Le Bean controller se multiplie. Mais a ce moment pas sur que le contexte soit cohérent pour FacesContext (est ce que Spring en créé un nouveau par proxy, ou par requete ou par application? Ce que J2EE ne faisait pas)

  6. #6
    Membre très actif Avatar de bruneltouopi
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2010
    Messages
    308
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Ile Maurice

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2010
    Messages : 308
    Par défaut
    Citation Envoyé par devyreham Voir le message
    juste cette ligne qui m'intrigue.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    FacesContext ctx = FacesContext.getCurrentInstance();
    C'est juste une piste. Les Bean Spring sont par défaut des singleton. Ici en "SessionScoped" ils y ajoutent un mecanisme de proxy. Le Bean controller se multiplie. Mais a ce moment pas sur que le contexte soit cohérent pour FacesContext (est ce que Spring en créé un nouveau par proxy, ou par requete ou par application? Ce que J2EE ne faisait pas)
    C'est justement une composante que je ne maitrise pas. je vais creusé avec @Scope("session") de Spring.car le partage de sessions avec @SessionScoped de jsf est effectif ce qui n'est pas tolerable.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Faille de sécurité avec les sessions ?
    Par goku19 dans le forum Langage
    Réponses: 8
    Dernier message: 19/03/2015, 14h00
  2. Sécurité avec les Sessions ?
    Par niavlys26 dans le forum Langage
    Réponses: 7
    Dernier message: 20/11/2009, 08h49
  3. Réponses: 9
    Dernier message: 04/07/2008, 11h53
  4. [Sécurité] securite avec les sessions.
    Par krapoulos dans le forum Langage
    Réponses: 7
    Dernier message: 05/11/2005, 14h41
  5. Problème avec les sessions
    Par philippef dans le forum Langage
    Réponses: 2
    Dernier message: 27/10/2005, 15h19

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo