JSF Authenticatie Inloggen Uitloggen Voorbeeld met Database

Het authenticatiemechanisme stelt gebruikers in staat om veilige toegang tot de toepassing te hebben door de gebruikersnaam en het wachtwoord te valideren. We zullen JSF-weergave gebruiken voor het inloggen, DAO-object, HttpSession voor sessiebeheer, JSF managed bean en mysql-database. Laten we nu gedetailleerd bekijken hoe we een JSF inlog- en uitlogauthenticatiemechanisme kunnen maken in de JSF-toepassing. Stap 1: Maak de tabel Gebruikers in de mysql-database als

CREATE TABLE Users( 
uid int(20) NOT NULL AUTO_INCREMENT, 
uname VARCHAR(60) NOT NULL, 
password VARCHAR(60) NOT NULL, 
PRIMARY KEY(uid));

Hier maken we een gebruikerstabel met uid als primaire sleutel, gebruikersnaam- en wachtwoordvelden met niet-nullbeperkingen. Stap 2: Voeg gegevens toe aan de tabel Gebruikers als;

INSERT INTO Users VALUES(1,'adam','adam');

Voordat we doorgaan naar onze projectgerelateerde code, toont onderstaande afbeelding de projectstructuur in Eclipse. Maak gewoon een dynamisch webproject aan en converteer het naar Maven om de projectsjabloon te krijgen en blijf dan verschillende componenten toevoegen. Stap 3: Maak de JSF inlogpagina login.xhtml als;

<?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>

Hier maken we een JSF inlogweergavepagina met gebruikersnaam- en wachtwoordvelden en stellen waarden in voor deze velden via de inlogbeheerde bean. We roepen de methode validateUsernamePassword aan bij het klikken op de knop Inloggen om de gebruikersnaam en het wachtwoord te valideren. Stap 4: Maak de beheerde bean Login.java als;

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;
	}

	//valideer inloggen
	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";
		}
	}

	//uitloggebeurtenis, sessie ongeldig maken
	public String logout() {
		HttpSession session = SessionUtils.getSession();
		session.invalidate();
		return "login";
	}
}

We verklaren drie String-variabelen user, pwd en msg voor de velden gebruikersnaam, wachtwoord en foutmelding, samen met de getter- en setter-methoden. We schrijven een methode validateUsernamePassword() om de gebruikersnaam- en wachtwoordvelden te valideren door de klasse LoginDAO op te roepen om de gebruikersnaam en het wachtwoord uit de database op te halen en deze te vergelijken met de doorgegeven waarden aan de frontend. Als de gebruikersnaam en het wachtwoord niet overeenkomen, wordt een foutmelding weergegeven als “Onjuiste gebruikersnaam en wachtwoord”. Ook wordt een logout()-methode geschreven om uit te loggen door de bijgevoegde HTTPSession ongeldig te maken. Stap 5: Maak nu de LoginDAO-java-klasse als volgt aan. Let op: de code voor databasebewerkingen is niet geoptimaliseerd voor gebruik in een echt project. Ik heb het zo snel mogelijk geschreven omdat het idee is om authenticatie te leren in JSF-toepassingen.

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()) {
				//resultaat gevonden, betekent geldige invoer
				return true;
			}
		} catch (SQLException ex) {
			System.out.println("Login error -->" + ex.getMessage());
			return false;
		} finally {
			DataConnect.close(con);
		}
		return false;
	}
}

In de validate()-methode stellen we eerst verbinding met de database door de klasse DataConnect op te roepen met de methode getConnection. We gebruiken PreparedStatement om de query te bouwen om de gegevens uit de database op te halen met de door de gebruiker ingevoerde waarden. Als we gegevens krijgen in de resultset, betekent dit dat de invoer geldig is en geven we true terug, anders false. Stap 6: Maak de klasse DataConnect.java als volgt aan;

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) {
		}
	}
}

We laden de JDBC-stuurprogramma (JDBC driver) met behulp van de Class.forName-methode en gebruiken de DriverManager.getConnection-methode waarbij de URL, gebruikersnaam en wachtwoord worden doorgegeven om verbinding te maken met de database. Stap 7: Maak SessionUtils.java aan om sessiegerelateerde gebruikersinformatie te verkrijgen en beheren.

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;
	}
}

Hier verkrijgen we een sessie voor elke ingelogde gebruiker via de getUserId-methode, waardoor een sessie-id wordt gekoppeld aan een specifieke gebruikers-id. Stap 8: Maak de autorisatiefilterklasse aan als;

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() {

	}
}

We implementeren de standaard filterklasse door de destroy- en doFilter-methoden te overschrijven. In de doFilter-methode sturen we de gebruiker door naar de inlogpagina als hij probeert toegang te krijgen tot een andere pagina zonder in te loggen. Stap 9: Maak admin.xhtml aan;

<?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>

Deze pagina wordt weergegeven wanneer de gebruiker succesvol inlogt. De uitlogfunctionaliteit wordt geïmplementeerd door de logout-methode van de klasse Login.java aan te roepen. Stap 10: Maak het bestand faces-config.xml aan;

<?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>

Zodra je alle stappen hierboven hebt voltooid, voer je de applicatie uit en bekijk je de volgende uitvoer in de browser. Aanmeldpagina Authenticatiefoutpagina Aanmeldingssuccespagina Toegang tot admin.xhtml tijdens het aanmelden Klik gewoon op de Logout-link en de sessie wordt ongeldig gemaakt, probeer daarna toegang te krijgen tot de admin.xhtml-pagina en je wordt doorverwezen naar de aanmeldpagina, ga verder en download het project vanaf onderstaande link en probeer het uit.

Download JSF Authenticatie Login Logout Project

Source:
https://www.digitalocean.com/community/tutorials/jsf-authentication-login-logout-database-example