2010-11-17 5 views
3

Comment authentifier un utilisateur à partir d'une action JSF (ou dans les méthodes de servlet doGet/doPost)? je veux dire quelque chose comme:Authentification par programmation Java EE 5

Authenticator auth = ...; 
if (!auth.authenticate("user","password")) 
{ 
    FacesContext.getInstance().addMessage("Incorrect username or password", null); 
} 

Restrictions:

  • Cette méthode doit être compatible avec la sécurité gérée par conteneur. (c'est-à-dire `HttpServletRequest.getRemoteUser()` doit renvoyer un utilisateur authentifié)
  • Cette méthode doit fonctionner partout (c'est-à-dire sur chaque serveur d'application).

Ne pas utiliser j_security_check ou d'un autre type d'authentification J2EE (BASIC, DIGEST, etc ...)

Il est possible?
Ou comment créer captcha de cette façon?
Validez que login et mot de passe ne sont pas vides?
sur une seule page et sans JavaScript, bien sûr ...

Des questions similaires ... mais sans réponse sur cette question:

JSF authentication and authorization
Performing user authentication in Java EE/JSF using j_security_check

Edit 1:
I Serlvet API moyenne au moins 2,3. Oui, je lis à propos de login dans Servlet API 3.0, mais il est pris en charge uniquement par les nouvelles versions des serveurs d'applications.

Je pense qu'il peut y avoir une solution qui implémente cette authentification pour chaque serveur d'application. Parfois, via certains hacks, parfois via des classes spéciales conçues à cet effet. Comme ceci:

private Class<?> tryClass(String name) 
{ 
    try 
    { 
     return Class.forName(name); 
    } 
    catch (ClassNotFoundException e) 
    { 
     return null; 
    } 
} 

public boolean authenticate(String username, String password) throws AuthenticationException 
{ 
    try 
    { 

     ExternalContext context = FacesContext.getCurrentInstance().getExternalContext(); 
     Object request = context.getRequest(); 
     Object response = context.getResponse(); 

     Class<?> authClass = tryClass("com.sun.appserv.security.ProgrammaticLogin"); 
     if (authClass != null) 
     { 
      return (Boolean)authClass.getMethod("login").invoke(
       authClass.newInstance(), "user", "password", request, response); 
     } 

     authClass = tryClass("org.jboss.web.tomcat.security.login.WebAuthentication"); 
     if (authClass != null) 
     { 
      return (Boolean)authClass.getMethod("login").invoke(
       authClass.newInstance(), "user", "password"); 
     } 

     // ... other hacks ...application servers 

    } 
    catch (Exception e) 
    { 
     throw new AuthenticationException("an error occured during user authentication", e); 
    } 

    return false; 
} 
+0

Utilisez-vous vraiment le vintage J2EE? Tu ne veux pas dire Java EE? Si oui, 5 ou 6? Java EE 5 ne propose aucune fonctionnalité pour l'authentification par programmation, Java EE 6 do, comme vous pouvez le lire dans la dernière question liée. – BalusC

+0

Je suis désolé. Java EE 5 bien sûr. Toujours les confondre. – ProgramWriter

+0

Vous avez mentionné Servlet 2.3. La servlet 2.3 fait partie de J2EE 1.3. Java EE 5 a Servlet 2.5. – BalusC

Répondre

1

Ah, c'est J2EE 1.3 Java EE 5. Dommage, vous n'avez pas de chance quand vous voulez aller de l'avant avec la sécurité gérée par conteneur. Vous devez récupérer les implémentations spécifiques au conteneur sous les couvertures. En passant, "sécurité gérée par conteneur sans j_security_check ou BASIC/DIGEST" est contradictoire. Personnellement, je voudrais juste oublier tout cela et la sécurité d'origine ou saisir une implémentation de tiers qui est plus configurable, comme Spring Security.

1

connexion est Programmatic sacrément difficile et semble varier selon le serveur d'applications. Je crois que le fait d'utiliser j_security_check est le plus efficace et permettra à votre application de fonctionner sur différents serveurs d'applications.

La partie la plus difficile consiste à faire accepter l'authentification par le serveur d'applications. Sur Tomcat, j'ai pu faire myLoginModule .login() et avoir le module de connexion réussi, mais l'utilisateur n'a pas été authentifié avec le conteneur. JBoss a du code pour que l'authentification par programmation fonctionne entre JBoss et Tomcat (puisque Tomcat vit dans JBoss). En regardant cela pour Glassfish, j'ai eu l'impression que la connexion programmatique est très difficile et devrait être laissée aux professionnels.

documentation Glassfish (http://docs.sun.com/app/docs/doc/820-4496/beacm?a=view) dit:

connexion est spécifique à Programmatic Enterprise Server et non portable vers d'autres serveurs d'applications.

Modifier

La méthode j_security_check prend un peu de temps pour s'y habituer, mais une fois que vous apprenez à travailler autour d'elle, peut être tout à fait réussie. Fondamentalement, vous pouvez avoir une page d'accueil qui redirige l'utilisateur dans votre application; Si l'utilisateur ne s'est pas encore connecté, il sera envoyé à votre page de connexion. Votre page de connexion peut être la page d'accueil de votre site. Une fois sur la page d'accueil, l'utilisateur peut naviguer vers d'autres pages "non sécurisées" de votre site. Vous pouvez également inclure des formulaires de connexion sur ces pages si vous le souhaitez. Vous n'êtes pas coincé avec une seule page de connexion.

Edit 2

J'utilise AJAX (via RichFaces) pour vérifier le nom d'utilisateur/mot de passe de l'utilisateur et affiche un message d'erreur en cas de besoin. Si les informations d'identification sont correctes, le formulaire pointant sur j_security_check est soumis à l'authentification réelle.

Edit 3

Le procédé de connexion par programme suggéré par BalusC sur la deuxième question liée (http://stackoverflow.com/questions/2206911/best-way-for-user-authentication-on-javaee -6-using-jsf-2-0) faisant request.login(...) semble bon. Je vais l'essayer bientôt o) Servlet 3 est supporté par Glassfish 3 mais pas grand chose d'autre (fera partie de Tomcat 7, probablement JBoss 6).

+0

Variez-vous? 'j_security_check' ** fait partie ** de l'API Java EE et est implémenté par tous les conteneurs Web Java EE. L'utilisation programmatique fournie par l'API est uniquement disponible depuis Java EE 6. – BalusC

+0

OK. Je voulais dire que le code de programmation nécessaire pour une connexion programmatique réussie (n'utilisant pas j_security_check) semble être différent entre les serveurs d'applications. –

+0

@BalusC Est-ce que EE 6 fournit des méthodes portables standard de connexion par programme? Si c'est le cas, ça serait vraiment cool. –