Après avoir cherché sur le Web et essayé de nombreuses façons différentes, voici ce que je suggérerais pour l'authentification Java EE 6:
Configurez le domaine de la sécurité:
Dans mon cas, j'avais les utilisateurs dans la base de données. J'ai donc suivi cet article de blog pour créer un royaume JDBC qui pourrait authentifier les utilisateurs en fonction du nom d'utilisateur et des mots de passe hachés MD5 dans ma table de base de données:
http://blog.gamatam.com/2009/11/jdbc-realm-setup-with-glassfish-v3.html
Remarque: le message parle d'un utilisateur et d'une table de groupe dans la base de données. J'avais une classe User avec un attribut enum UserType mappé via des annotations javax.persistence à la base de données. J'ai configuré le royaume avec la même table pour les utilisateurs et les groupes, en utilisant la colonne userType comme colonne de groupe et cela a bien fonctionné.
Utilisez l'authentification par formulaire:
Toujours en suivant le billet de blog ci-dessus, configurez votre web.xml et sun-web.xml, mais au lieu d'utiliser l'authentification BASIC, utilisez FORM (en fait, peu importe celui que vous utilisez, mais j'ai fini par utiliser FORM). Utilisez le HTML standard, pas le JSF.
Ensuite, utilisez le conseil de BalusC ci-dessus sur l'initialisation paresseuse des informations utilisateur à partir de la base de données. Il a suggéré de le faire dans un bean géré en obtenant le principal du contexte des visages. J'ai utilisé, à la place, un bean session avec état pour stocker les informations de session pour chaque utilisateur, j'ai donc injecté le contexte de session:
@Resource
private SessionContext sessionContext;
Avec le mandant, je peux vérifier le nom d'utilisateur et, en utilisant le gestionnaire d'entités EJB, obtenir les informations utilisateur de la base de données et les stocker dans mon SessionInformation
EJB.
Se déconnecter:
J'ai également cherché le meilleur moyen de me déconnecter. Le meilleur que j'ai trouvé utilise un servlet:
@WebServlet(name = "LogoutServlet", urlPatterns = {"/logout"})
public class LogoutServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HttpSession session = request.getSession(false);
// Destroys the session for this user.
if (session != null)
session.invalidate();
// Redirects back to the initial page.
response.sendRedirect(request.getContextPath());
}
}
Bien que ma réponse soit vraiment tardive compte tenu de la date de la question, j'espère que cela aidera d'autres personnes qui se retrouvent ici de Google, tout comme moi.
Ciao,
Vítor Souza
HttpServletResponse#login(user, password)
, de cette façon, vous pouvez simplement obtenir de la base de données le sel de l'utilisateur, les itérations et tout ce que vous utilisez pour le salage, hacher le mot de passe que l'utilisateur a entré à l'aide de ce sel, puis demander au conteneur de s'authentifier avecHttpServletResponse#login(user, password)
.Je suppose que vous voulez une authentification par formulaire utilisant des descripteurs de déploiement et
j_security_check
.Vous pouvez également le faire dans JSF en utilisant simplement les mêmes noms de champ prédéfinis
j_username
etj_password
comme illustré dans le didacticiel.Par exemple
Vous pouvez effectuer un chargement paresseux dans le
User
getter pour vérifier si leUser
est déjà connecté et sinon, vérifier si lePrincipal
est présent dans la requête et si c'est le cas, obtenir leUser
associé avecj_username
.Le
User
est évidemment accessible dans JSF EL par#{auth.user}
.Pour vous déconnecter, faites un
HttpServletRequest#logout()
(et définissez-leUser
sur null!). Vous pouvez obtenir une poignée deHttpServletRequest
JSF dansExternalContext#getRequest()
. Vous pouvez également simplement invalider complètement la session.Pour le reste (définition des utilisateurs, des rôles et des contraintes dans le descripteur de déploiement et le domaine), suivez simplement le didacticiel Java EE 6 et la documentation servletcontainer de la manière habituelle.
Mise à jour : vous pouvez également utiliser le nouveau Servlet 3.0
HttpServletRequest#login()
pour effectuer une connexion par programme au lieu d'utiliserj_security_check
ce qui peut ne pas être accessible en soi par un répartiteur dans certains conteneurs de servlet. Dans ce cas , vous pouvez utiliser une forme fullworthy JSF et un haricot avecusername
etpassword
propriétés et unelogin
méthode qui ressemblent à ceci:Et cette vue a une portée gérée bean qui se souvient également de la page initialement demandée:
De cette façon, le
User
est accessible dans JSF EL par#{user}
.la source
j_security_check
peut ne pas fonctionner sur tous les conteneurs de servlet.@WebServlet(name="testServlet", urlPatterns={"/ testServlet "}) @ServletSecurity(@HttpConstraint(rolesAllowed = {"testUser", "admin”}))
Et sur une méthode par méthode niveau:@ServletSecurity(httpMethodConstraints={ @HttpMethodConstraint("GET"), @HttpMethodConstraint(value="POST", rolesAllowed={"testUser"})})
FacesServlet
et vous ne pouvez pas (et ne voulez pas) le modifier.RequestDispatcher.FORWARD_REQUEST_URI
. Les attributs de demande sont dans JSF disponibles parExternalContext#getRequestMap()
.Il faut mentionner que c'est une option pour laisser complètement les problèmes d'authentification au contrôleur frontal, par exemple un serveur Web Apache et évaluer à la place HttpServletRequest.getRemoteUser (), qui est la représentation JAVA de la variable d'environnement REMOTE_USER. Cela permet également des conceptions de connexion sophistiquées telles que l'authentification Shibboleth. Le filtrage des demandes vers un conteneur de servlet via un serveur Web est une bonne conception pour les environnements de production, souvent mod_jk est utilisé pour le faire.
la source
Le problème HttpServletRequest.login ne définit pas l'état d'authentification dans la session a été résolu dans la version 3.0.1. Mettez à jour glassfish vers la dernière version et vous avez terminé.
La mise à jour est assez simple:
la source