مثال على تسجيل الدخول وتسجيل الخروج لمصادقة JSF Database

آلية المصادقة تتيح للمستخدمين الوصول الآمن إلى التطبيق عن طريق التحقق من اسم المستخدم وكلمة المرور. سنستخدم عرض JSF لتسجيل الدخول، وكائن DAO، وHttpSession لإدارة الجلسة، و JSF managed bean وقاعدة بيانات mysql. دعونا نلقي الآن نظرة مفصلة على كيفية إنشاء آلية مصادقة تسجيل الدخول لـ JSF التطبيق. الخطوة 1: إنشاء جدول Users في قاعدة بيانات mysql على النحو التالي

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

هنا نقوم بإنشاء جدول المستخدمين مع معرف المستخدم كرئيسي وحقول اسم المستخدم وكلمة المرور مع قيود “لا يمكن أن يكون فارغًا”. الخطوة 2: إدخال البيانات في جدول Users على النحو التالي؛

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

قبل أن ننتقل إلى كود المشروع ذي الصلة، يظهر الصورة أدناه هيكل المشروع في Eclipse. ما عليك سوى إنشاء مشروع ويب ديناميكي وتحويله إلى مافن للحصول على بدء المشروع ثم قم بإضافة مكونات مختلفة. الخطوة 3: إنشاء صفحة تسجيل دخول JSF login.xhtml على النحو التالي؛

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

هنا نقوم بإنشاء صفحة عرض تسجيل الدخول JSF مع حقول اسم المستخدم وكلمة المرور وتعيين قيم لهذه الحقول من خلال الكائن المدار بواسطة تسجيل الدخول. نقوم بتنفيذ طريقة validateUsernamePassword عند النقر فوق زر تسجيل الدخول للتحقق من اسم المستخدم وكلمة المرور. الخطوة 4: إنشاء الكائن المدار Login.java على النحو التالي؛

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

	//التحقق من تسجيل الدخول
	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";
		}
	}

	//حدث تسجيل الخروج، إبطال الجلسة
	public String logout() {
		HttpSession session = SessionUtils.getSession();
		session.invalidate();
		return "login";
	}
}

نعلن عن ثلاث متغيرات String تسمى user و pwd و msg لحقول اسم المستخدم وكلمة المرور ورسالة الخطأ مع أساليب getter و setter. نكتب طريقة `validateUsernamePassword()` لتحقق حقلي اسم المستخدم وكلمة المرور عن طريق استدعاء فئة `LoginDAO` لاسترداد اسم المستخدم وكلمة المرور من قاعدة البيانات ومقارنتها مع القيم الممررة من الواجهة الأمامية. إذا لم يتطابق اسم المستخدم وكلمة المرور، يتم عرض رسالة خطأ “اسم المستخدم أو كلمة المرور غير صحيحة”. أيضًا، يتم كتابة طريقة `logout()` للقيام بتسجيل الخروج من خلال إلغاء صلاحية الـ HTTPSession المرفقة. الخطوة 5: الآن قم بإنشاء فئة `LoginDAO` الجافا كما هو موضح أدناه. يرجى ملاحظة أن رمز عمليات قاعدة البيانات غير محسن للاستخدام في مشروع حقيقي، لقد كتبته بأسرع ما يمكن لأن الفكرة هي تعلم المصادقة في تطبيقات 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()) {
				//تم العثور على نتيجة، يعني إدخالات صحيحة
				return true;
			}
		} catch (SQLException ex) {
			System.out.println("Login error -->" + ex.getMessage());
			return false;
		} finally {
			DataConnect.close(con);
		}
		return false;
	}
}

في طريقة `validate()` ننشأ الاتصال أولا بقاعدة البيانات باستدعاء فئة `DataConnect` ثم نستخدم `PreparedStatement` لبناء الاستعلام لاسترداد البيانات من قاعدة البيانات بقيم المستخدم المدخلة. إذا حصلنا على أي بيانات في مجموعة النتائج، يعني ذلك أن الإدخال صحيح ونعيد قيمة صحيحة، وإلا فإننا نعيد قيمة خاطئة. الخطوة 6: قم بإنشاء فئة `DataConnect.java` كما يلي؛

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

نقوم بتحميل برنامج تشغيل JDBC باستخدام طريقة Class.forName ونستخدم طريقة DriverManager.getConnection بواسطة تمرير الرابط واسم المستخدم وكلمة المرور للاتصال بقاعدة البيانات. الخطوة 7: قم بإنشاء ملف SessionUtils.java للحصول على معلومات المستخدم المتعلقة بالجلسة وإدارتها.

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

هنا نحصل على جلسة لكل مستخدم يقوم بتسجيل الدخول من خلال طريقة getUserId وبالتالي نربط معرف الجلسة بمعرف المستخدم المحدد. الخطوة 8: قم بإنشاء فئة مرشح الصلاحيات كما يلي؛

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

	}
}

نقوم بتنفيذ فئة المرشح القياسية عن طريق تجاوز طرق destroy و doFilter. في طريقة doFilter سنقوم بإعادة توجيه المستخدم إلى صفحة تسجيل الدخول إذا حاول الوصول إلى صفحة أخرى دون تسجيل الدخول. الخطوة 9: قم بإنشاء admin.xhtml كما يلي؛

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

يتم عرض هذه الصفحة عند تسجيل المستخدم بنجاح. يتم تنفيذ وظيفة تسجيل الخروج عن طريق استدعاء طريقة logout في فئة Login.java. الخطوة 10: قم بإنشاء ملف faces-config.xml كما يلي؛

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

بمجرد الانتهاء من جميع الخطوات المحددة أعلاه، قم بتشغيل التطبيق وانظر إلى الإخراج التالي في المتصفح. صفحة تسجيل الدخول صفحة خطأ في المصادقة صفحة نجاح تسجيل الدخول الوصول إلى admin.xhtml بينما مسجل الدخول ما عليك سوى النقر على رابط تسجيل الخروج وسيتم إبطال الجلسة، بعد ذلك حاول الوصول إلى صفحة admin.xhtml وسيتم توجيهك إلى صفحة تسجيل الدخول، تابع وقم بتنزيل المشروع من الرابط أدناه وجربه.

تنزيل مشروع JSF المتعلق بالمصادقة وتسجيل الدخول والخروج

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