El mecanismo de autenticación permite a los usuarios tener acceso seguro a la aplicación mediante la validación del nombre de usuario y la contraseña. Utilizaremos la vista JSF para el inicio de sesión, el objeto DAO, HttpSession para la gestión de sesiones, el bean gestionado JSF y la base de datos MySQL. Veamos ahora en detalle cómo crear un mecanismo de autenticación de inicio y cierre de sesión de JSF en la aplicación JSF. Paso 1: Crear la tabla Users en la base de datos MySQL como
CREATE TABLE Users(
uid int(20) NOT NULL AUTO_INCREMENT,
uname VARCHAR(60) NOT NULL,
password VARCHAR(60) NOT NULL,
PRIMARY KEY(uid));
Aquí creamos la tabla de usuarios con uid como clave primaria, campos de nombre de usuario y contraseña con restricciones de no nulos. Paso 2: Insertar datos en la tabla Users como;
INSERT INTO Users VALUES(1,'adam','adam');
Antes de pasar al código relacionado con nuestro proyecto, la siguiente imagen muestra la estructura del proyecto en Eclipse. Simplemente crea un proyecto web dinámico y conviértelo en Maven para obtener el esqueleto del proyecto y luego sigue añadiendo diferentes componentes. Paso 3: Crear la página de inicio de sesión de JSF
login.xhtml
como;
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="https://www.w3.org/1999/xhtml"
xmlns:h="https://java.sun.com/jsf/html">
<h:head>
<title>login</title>
</h:head>
<h:body>
<h:form>
<h3>JSF Login Logout</h3>
<h:outputText value="Username" />
<h:inputText id="username" value="#{login.user}"></h:inputText>
<h:message for="username"></h:message>
<br></br><br></br>
<h:outputText value="Password" />
<h:inputSecret id="password" value="#{login.pwd}"></h:inputSecret>
<h:message for="password"></h:message>
<br></br><br></br>
<h:commandButton action="#{login.validateUsernamePassword}"
value="Login"></h:commandButton>
</h:form>
</h:body>
</html>
Aquí estamos creando una página de vista de inicio de sesión de JSF con campos de nombre de usuario y contraseña, y establecemos valores para estos campos a través del bean gestionado de inicio de sesión. Invocamos el método validateUsernamePassword
al hacer clic en el botón de inicio de sesión para validar el nombre de usuario y la contraseña. Paso 4: Crear el bean gestionado Login.java
como;
package com.journaldev.jsf.beans;
import java.io.Serializable;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;
import javax.servlet.http.HttpSession;
import com.journaldev.jsf.dao.LoginDAO;
import com.journaldev.jsf.util.SessionUtils;
@ManagedBean
@SessionScoped
public class Login implements Serializable {
private static final long serialVersionUID = 1094801825228386363L;
private String pwd;
private String msg;
private String user;
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public String getUser() {
return user;
}
public void setUser(String user) {
this.user = user;
}
//validar inicio de sesión
public String validateUsernamePassword() {
boolean valid = LoginDAO.validate(user, pwd);
if (valid) {
HttpSession session = SessionUtils.getSession();
session.setAttribute("username", user);
return "admin";
} else {
FacesContext.getCurrentInstance().addMessage(
null,
new FacesMessage(FacesMessage.SEVERITY_WARN,
"Incorrect Username and Passowrd",
"Please enter correct username and Password"));
return "login";
}
}
//evento de cierre de sesión, invalidar sesión
public String logout() {
HttpSession session = SessionUtils.getSession();
session.invalidate();
return "login";
}
}
Declaramos tres variables String user, pwd y msg para los campos de nombre de usuario, contraseña y mensaje de error junto con los métodos getter y setter. Escribimos un método validateUsernamePassword()
para validar el campo de nombre de usuario y contraseña invocando la clase LoginDAO
para obtener el nombre de usuario y la contraseña de la base de datos y comparándolos con los valores del front end pasados. Si el nombre de usuario y la contraseña no coinciden, se muestra un mensaje de error como “Nombre de usuario y contraseña incorrectos”. También se escribe un método logout()
para realizar el cierre de sesión invalidando la HttpSession adjunta. Paso 5: Ahora crea la clase Java LoginDAO como se muestra a continuación. Ten en cuenta que el código de operaciones de base de datos no está optimizado para ser utilizado en un proyecto real, lo escribí lo más rápido posible porque la idea es aprender la autenticación en aplicaciones JSF.
package com.journaldev.jsf.dao;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import com.journaldev.jsf.util.DataConnect;
public class LoginDAO {
public static boolean validate(String user, String password) {
Connection con = null;
PreparedStatement ps = null;
try {
con = DataConnect.getConnection();
ps = con.prepareStatement("Select uname, password from Users where uname = ? and password = ?");
ps.setString(1, user);
ps.setString(2, password);
ResultSet rs = ps.executeQuery();
if (rs.next()) {
//resultado encontrado, significa entradas válidas
return true;
}
} catch (SQLException ex) {
System.out.println("Login error -->" + ex.getMessage());
return false;
} finally {
DataConnect.close(con);
}
return false;
}
}
En el método validate()
primero establecemos la conexión a la base de datos invocando el método getConnection
de la clase DataConnect
. Usamos PreparedStatement
para construir la consulta para obtener los datos de la base de datos con los valores ingresados por el usuario. Si obtenemos algún dato en el conjunto de resultados, significa que la entrada es válida y devolvemos true, de lo contrario false. Paso 6: Crea la clase DataConnect.java
como;
package com.journaldev.jsf.util;
import java.sql.Connection;
import java.sql.DriverManager;
public class DataConnect {
public static Connection getConnection() {
try {
Class.forName("com.mysql.jdbc.Driver");
Connection con = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/cardb", "pankaj", "pankaj123");
return con;
} catch (Exception ex) {
System.out.println("Database.getConnection() Error -->"
+ ex.getMessage());
return null;
}
}
public static void close(Connection con) {
try {
con.close();
} catch (Exception ex) {
}
}
}
Cargamos el controlador JDBC usando el método Class.forName
y utilizamos el método DriverManager.getConnection
pasando la URL, el nombre de usuario y la contraseña para conectarnos a la base de datos. Paso 7: Creamos SessionUtils.java para obtener y gestionar la información de usuario relacionada con la sesión.
package com.journaldev.jsf.beans;
import javax.faces.context.FacesContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
public class SessionUtils {
public static HttpSession getSession() {
return (HttpSession) FacesContext.getCurrentInstance()
.getExternalContext().getSession(false);
}
public static HttpServletRequest getRequest() {
return (HttpServletRequest) FacesContext.getCurrentInstance()
.getExternalContext().getRequest();
}
public static String getUserName() {
HttpSession session = (HttpSession) FacesContext.getCurrentInstance()
.getExternalContext().getSession(false);
return session.getAttribute("username").toString();
}
public static String getUserId() {
HttpSession session = getSession();
if (session != null)
return (String) session.getAttribute("userid");
else
return null;
}
}
Aquí obtenemos una sesión para cada usuario que inicia sesión a través del método getUserId asociando así un ID de sesión a un ID de usuario particular. Paso 8: Creamos la clase de filtro de autorización como;
package com.journaldev.jsf.filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
@WebFilter(filterName = "AuthFilter", urlPatterns = { "*.xhtml" })
public class AuthorizationFilter implements Filter {
public AuthorizationFilter() {
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
try {
HttpServletRequest reqt = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
HttpSession ses = reqt.getSession(false);
String reqURI = reqt.getRequestURI();
if (reqURI.indexOf("/login.xhtml") >= 0
|| (ses != null && ses.getAttribute("username") != null)
|| reqURI.indexOf("/public/") >= 0
|| reqURI.contains("javax.faces.resource"))
chain.doFilter(request, response);
else
resp.sendRedirect(reqt.getContextPath() + "/faces/login.xhtml");
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
@Override
public void destroy() {
}
}
Implementamos la clase de filtro estándar sobrescribiendo los métodos destroy y doFilter. En el método doFilter redirigiremos al usuario a la página de inicio de sesión si intenta acceder a otra página sin haber iniciado sesión. Paso 9: Creamos admin.xhtml
como;
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="https://www.w3.org/1999/xhtml"
xmlns:h="https://java.sun.com/jsf/html">
<h:head>
<title>Facelet Title</title>
</h:head>
<h:body>
<h:form>
<p>Welcome #{login.user}</p>
<h:commandLink action="#{login.logout}" value="Logout"></h:commandLink>
</h:form>
</h:body>
</html>
Esta página se renderiza cuando el usuario inicia sesión correctamente. La funcionalidad de cierre de sesión se implementa llamando al método logout de la clase Login.java
. Paso 10: Creamos el archivo faces-config.xml
como;
<?xml version='1.0' encoding='UTF-8'?>
<faces-config version="2.2" xmlns="https://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://xmlns.jcp.org/xml/ns/javaee
https://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_2.xsd">
<navigation-rule>
<from-view-id>/login.xhtml</from-view-id>
<navigation-case>
<from-outcome>admin</from-outcome>
<to-view-id>/admin.xhtml</to-view-id>
</navigation-case>
</navigation-rule>
</faces-config>
Una vez que hayas completado todos los pasos especificados anteriormente, ejecuta la aplicación y observa la siguiente salida en el navegador. Página de inicio de sesión Página de error de autenticación
Página de inicio de sesión exitosa
Accediendo a admin.xhtml mientras estás conectado
Simplemente haz clic en el enlace de Cerrar sesión y la sesión se invalidará, luego intenta acceder a la página admin.xhtml y serás redirigido a la página de inicio de sesión, adelante y descarga el proyecto desde el siguiente enlace y pruébalo.
Descargar Proyecto de Inicio de Sesión y Cierre de Sesión de Autenticación JSF
Source:
https://www.digitalocean.com/community/tutorials/jsf-authentication-login-logout-database-example