2017-02-17 1 views
0

Je suis en train d'ajouter me souviens fonctionnalité à mon application, mais pour une raison quelconque le HttpServletRequest.login() jette un ServletException:Se souvenir de moi connexion automatique avec JSF + JAAS

javax.servlet.ServletException: Login failed 
at com.cleanup.filter.AutoLoginFilter.doFilter(AutoLoginFilter.java:71) 

Ligne 71:

req.login(adminUser.getEmail(), adminUser.getPwd()); 

Je sais que, selon les docs:

Lance: ServletException - si le mécanisme de connexion configuré ne prend pas en charge l'authentification par mot de passe du nom d'utilisateur, ou si une identité d'appelant non nulle a déjà été établie (avant l'appel), ou si la validation du nom d'utilisateur et le mot de passe échoue

Ce qui, à son tour signifierait que les informations d'identification sont « invalides », qui est pas vrai, puisque le journal dans le mécanisme fonctionne très bien.

Mais pourquoi lancer cette exception alors?

Ma théorie est que c'est dû au fait que le password est crypté, mais si tel est le cas, ne devrait pas request.login(..,..) fonctionne également avec le mot de passe déjà haché?

Voici mon filtre:

public void doFilter(ServletRequest request, ServletResponse response, 
     FilterChain chain) 
     throws IOException, ServletException { 


    HttpServletRequest req = (HttpServletRequest) request; 
    HttpServletResponse resp = (HttpServletResponse) response; 

    String remoteUser = (String) req.getRemoteUser(); 

    if (remoteUser == null) { 

     String uuid = CookieRememberUtil.getCookieValue(req); 

     System.out.println("Found cookie" + uuid); 

     if (uuid != null) { 
      AdminUsers adminUser = cookiesFacade.getAdminUserFromUUID(uuid); 

      if (adminUser != null) { 

       req.login(adminUser.getEmail(), adminUser.getPwd()); 
       CookieRememberUtil.addCookie(resp, uuid); 
      } else { 
       CookieRememberUtil.removeCookie(resp); 
      } 
     } 

    } 
    chain.doFilter(request, response); 

} 

Répondre

0

Le problème est la mise en œuvre du royaume sous-jacent qui sauvegarde votre processus de connexion.

La méthode de connexion renvoie inévitablement au domaine configuré pour effectuer cette authentification. Par exemple, si vous utilisez un domaine DB, le domaine recherche l'utilisateur dans la base de données, compare les mots de passe, puis extrait les informations de rôle. Donc, ce que vous devez faire est de rendre votre royaume "conscient de cookie". C'est-à-dire, lorsque vous cliquez sur votre filtre, vous pouvez vérifier votre cookie "remember me", et transmettre cette information à la méthode de connexion, afin qu'elle arrive finalement à votre domaine personnalisé, qui fait alors le bon choix chose.

String uuid = CookieRememberUtil.getCookieValue(req); 
if (uuid != null) { 
    req.login("***REMEMBER_ME***", uuid); 
} else { 
    ... run your normal login logic 
} 

Le royaume ressemble alors à l'utilisateur magique, qui est le nom est « Remember_Me », et utilise le UUID extraire les informations d'identification, et de construire le principal. Ensuite, en règle générale, vous ne pouvez pas autoriser des éléments tels que "*" à partir des noms d'utilisateur, de sorte qu'il est plus difficile pour quelqu'un de se connecter et de vous envoyer un spam avec des UUID pour essayer d'y accéder. Vous vérifiez cela lors de la connexion, et tout simplement annuler avec un nom d'utilisateur invalide, utilisateur introuvable, etc.

Donc, TLDR, vous avez besoin d'un domaine personnalisé pour votre conteneur.

Edit:

Pour que le conteneur pour effectuer l'autorisation, il utilise un concept appelé un royaume.Un domaine est le code qui valide l'utilisateur, vérifie son mot de passe et charge ses rôles en créant un Principal. Tous les conteneurs sont livrés avec des domaines intégrés qui font des choses de base: travailler avec un fichier plat, travailler avec une base de données, peut-être travailler avec un serveur LDAP.

Vous pouvez écrire une implémentation de domaine personnalisée et l'installer dans votre conteneur. Il s'agit généralement d'une interface plutôt simple que vous implémentez.

L'OBJET ENTIER du Royaume est de prendre des informations d'identification et de renvoyer un Principal. À l'aide de la fonction de connexion par programmation de Servlet 3.x, vous pouvez choisir non seulement quand effectuer l'appel de connexion, mais aussi les informations d'identification à transmettre au domaine.

Normalement, vous transmettez le nom d'utilisateur et son mot de passe. The Realm recherche le nom d'utilisateur, hache le mot de passe, le compare à ce qui est stocké, et voila, crée un Principal simple et le renvoie. Dans votre cas, lorsque vous disposez du cookie REMEMBER_ME, plutôt que de renvoyer le nom d'utilisateur et le mot de passe (que vous n'avez pas, puisque vous ne l'avez pas demandé), vous renvoyez le cookie ou les données peut extraire du cookie. Mais votre seule interface au Royaume, via la méthode de connexion, accepte un nom d'utilisateur et un mot de passe. En vérité, il accepte deux chaînes, qui peuvent être un nom d'utilisateur et un mot de passe. En vérité, ils peuvent être n'importe quel - comme un drapeau indique au domaine de se connecter via une valeur de cookie, et la valeur de cookie associée.

Le domaine utilise la valeur de cookie pour rechercher l'identité et créer un principal approprié. Le Principal que vous renvoyez n'a pas besoin d'avoir le même "nom d'utilisateur" que le premier paramètre de la fonction de connexion, il peut renvoyer n'importe quel Principal qu'il veut.

+0

Je ne suis pas certaine de vous avoir compris. – shep