java-ee forms-authentication stay-logged-in

java ee - Cómo implementar "Permanecer conectado" cuando el usuario inicia sesión en la aplicación web



java-ee forms-authentication (3)

No puede iniciar sesión completamente en un usuario a través de HttpServletRequest.login (nombre de usuario, contraseña) ya que no debe mantener tanto la contraseña de usuario como la de texto plano en la base de datos. Además, no puede realizar este inicio de sesión con un hash de contraseña que se guarda en la base de datos. Sin embargo, debe identificar a un usuario con un token de cookie / base de datos pero iniciar sesión sin ingresar contraseña usando el módulo de inicio de sesión personalizado (clase Java) basado en la API del servidor de Glassfish.

Vea los siguientes enlaces para más detalles:

http://www.lucubratory.eu/custom-jaas-realm-for-glassfish-3/

Mecanismo de seguridad personalizado en la aplicación Java EE 6/7

En la mayoría de los sitios web, cuando el usuario está a punto de proporcionar el nombre de usuario y la contraseña para iniciar sesión en el sistema, hay una casilla de verificación como "Permanecer conectado". Si marca la casilla, lo mantendrá conectado en todas las sesiones desde el mismo navegador web. ¿Cómo puedo implementar lo mismo en Java EE?

Estoy usando la autenticación administrada por contenedor basada en FORMULARIO con una página de inicio de sesión JSF.

<security-constraint> <display-name>Student</display-name> <web-resource-collection> <web-resource-name>CentralFeed</web-resource-name> <description/> <url-pattern>/CentralFeed.jsf</url-pattern> </web-resource-collection> <auth-constraint> <description/> <role-name>STUDENT</role-name> <role-name>ADMINISTRATOR</role-name> </auth-constraint> </security-constraint> <login-config> <auth-method>FORM</auth-method> <realm-name>jdbc-realm-scholar</realm-name> <form-login-config> <form-login-page>/index.jsf</form-login-page> <form-error-page>/LoginError.jsf</form-error-page> </form-login-config> </login-config> <security-role> <description>Admin who has ultimate power over everything</description> <role-name>ADMINISTRATOR</role-name> </security-role> <security-role> <description>Participants of the social networking Bridgeye.com</description> <role-name>STUDENT</role-name> </security-role>


Normalmente esto se hace así:

Cuando inicia sesión en un usuario, también establece una cookie en el cliente (y almacena el valor de la cookie en la base de datos) que expira después de un cierto tiempo (generalmente de 1 a 2 semanas).

Cuando ingresa una nueva solicitud, comprueba que exista cierta cookie y, si es así, busque en la base de datos para ver si coincide con cierta cuenta. Si coincide, entonces "sueltamente" iniciará sesión en esa cuenta. Cuando digo vagamente quiero decir que solo dejas que esa sesión lea información y no escriba información. Deberá solicitar la contraseña para permitir las opciones de escritura.

Esto es todo lo que es. El truco es asegurarse de que un inicio de sesión "flojo" no pueda causar mucho daño al cliente. Esto de alguna manera protegerá al usuario de alguien que agarra su cookie "remember me" e intenta iniciar sesión como él.


Utilice una cookie de larga duración para rastrear el cliente único y use el nuevo inicio de sesión programático proporcionado por Servlet 3.0 API HttpServletRequest#login() cuando el usuario no está conectado pero la cookie está presente.

Esta es la forma más fácil de lograr si administra los usuarios en una tabla de base de datos que proporciona JDBCRealm a Glassfish y es la misma tabla de donde proviene su entidad de User . A continuación, podría crear otra tabla con un valor de java.util.UUID como PK y la ID del usuario en cuestión como FK.

Asuma el siguiente formulario de inicio de sesión:

<form action="login" method="post"> <input type="text" name="username" /> <input type="password" name="password" /> <input type="checkbox" name="remember" value="true" /> <input type="submit" /> </form>

Y lo siguiente en el método doPost() de un Servlet que está mapeado en /login :

String username = request.getParameter("username"); String password = hash(request.getParameter("password")); boolean remember = "true".equals(request.getParameter("remember")); User user = userDAO.find(username, password); if (user != null) { request.login(user.getUsername(), user.getPassword()); // Password should already be the hashed variant. request.getSession().setAttribute("user", user); if (remember) { String uuid = UUID.randomUUID().toString(); rememberDAO.save(uuid, user); addCookie(response, COOKIE_NAME, uuid, COOKIE_AGE); } else { rememberDAO.delete(user); removeCookie(response, COOKIE_NAME); } }

(El COOKIE_NAME debe ser el nombre único de la cookie, por ejemplo, "remember" y el COOKIE_AGE debe ser la edad en segundos, por ejemplo, 2592000 durante 30 días)

Así es como se doFilter() método doFilter() de un Filter que está correlacionado en páginas restringidas:

HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) res; User user = request.getSession().getAttribute("user"); if (user == null) { String uuid = getCookieValue(request, COOKIE_NAME); if (uuid != null) { user = rememberDAO.find(uuid); if (user != null) { request.login(user.getUsername(), user.getPassword()); request.getSession().setAttribute("user", user); // Login. addCookie(response, COOKIE_NAME, uuid, COOKIE_AGE); // Extends age. } else { removeCookie(response, COOKIE_NAME); } } } if (user == null) { response.sendRedirect("login"); } else { chain.doFilter(req, res); }

En combinación con esos métodos de ayuda de cookies (es una lástima que falten en la API de Servlet):

public static String getCookieValue(HttpServletRequest request, String name) { Cookie[] cookies = request.getCookies(); if (cookies != null) { for (Cookie cookie : cookies) { if (name.equals(cookie.getName())) { return cookie.getValue(); } } } return null; } public static void addCookie(HttpServletResponse response, String name, String value, int maxAge) { Cookie cookie = new Cookie(name, value); cookie.setPath("/"); cookie.setMaxAge(maxAge); response.addCookie(cookie); } public static void removeCookie(HttpServletResponse response, String name) { addCookie(response, name, null, 0); }

Aunque el UUID es extremadamente difícil de usar, puede proporcionar al usuario la opción de bloquear la opción "recordar" en la dirección IP del usuario ( request.getRemoteAddr() ) y almacenarla / compararla también en la base de datos. Esto lo hace un poco más robusto.

También es una buena práctica reemplazar el valor de UUID siempre que el usuario haya cambiado su contraseña.