CyStack logo
  • Sản phẩm & Dịch vụ
  • Giải pháp
  • Bảng giá
  • Công ty
  • Tài liệu
Vi

vi

Trang chủHướng dẫnXác thực người dùng với JSF
Java

Xác thực người dùng với JSF

CyStack blog 6 phút để đọc
CyStack blog05/08/2025
Locker Avatar

Bao Tran

Web Developer

Locker logo social
Reading Time: 6 minutes

Cơ chế xác thực đăng nhập giúp người dùng truy cập ứng dụng một cách an toàn thông qua việc xác thực username và password.

Trong bài này, ta sẽ sử dụng JSF view cho trang đăng nhập, đối tượng DAO, HttpSession để quản lý session, bean do JSF quản lý (managed bean) và cơ sở dữ liệu MySQL. Hãy cùng xem chi tiết cách tạo một cơ chế xác thực người dùng với JSF.

Xác thực người dùng với JSF

Bước 1: Tạo bảng Users trong database MySQL như sau:

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

Bảng này có uid là khóa chính, cùng hai trường usernamepassword với ràng buộc not null.

Bước 2: Tiếp theo, chèn một vài dữ liệu vào bảng Users:

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

Trước khi đi vào phần code của project ví dụ, hãy xem qua cấu trúc của nó trong Eclipse ở hình dưới. Bạn chỉ cần tạo một project web động và chuyển đổi nó sang Maven để có một sườn ban đầu. Sau đó ta sẽ thêm dần các thành phần khác vào.

Cấu trúc project mẫu dùng xác thức người dùng với JSF

Bước 3: Tạo trang đăng nhập JSF login.xhtml như sau:

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

Ở đây, ta tạo một trang view JSF cho việc đăng nhập, bao gồm các trường username và password. Giá trị của các trường này được thiết lập thông qua login managed bean. Khi người dùng nhấn nút Login, ta sẽ gọi phương thức validateUsernamePassword để xác thực username và password.

Bước 4: Tạo managed bean trong file Login.java như sau:

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

	//validate login
	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";
		}
	}

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

Ta khai báo ba biến String là user, pwdmsg tương ứng cho username, password và thông báo lỗi, kèm theo các phương thức getter và setter (các phương thức dùng để thức lấy và đặt các giá trị).

Phương thức validateUsernamePassword() được dùng để xác thực username và password. Nó sẽ gọi class LoginDAO để lấy thông tin từ database rồi so sánh với giá trị người dùng nhập vào ở giao diện.

Nếu username và password không khớp, một thông báo lỗi “Incorrect username and password” sẽ được hiển thị. Ngoài ra, ta còn có phương thức logout để thực hiện việc đăng xuất bằng cách vô hiệu hóa HttpSession hiện tại.

Bước 5: Bây giờ, hãy tạo class Java LoginDAO như dưới đây. Lưu ý rằng code xử lý database chưa được tối ưu để dùng trong một dự án thực tế. Ở đây ta viết nó một cách nhanh nhất có thể vì mục đích chính là để học về xác thực trong ứng dụng 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()) {
				//result found, means valid inputs
				return true;
			}
		} catch (SQLException ex) {
			System.out.println("Login error -->" + ex.getMessage());
			return false;
		} finally {
			DataConnect.close(con);
		}
		return false;
	}
}

Trong phương thức validate(), đầu tiên ta thiết lập kết nối tới database bằng cách gọi phương thức getConnection của class DataConnect. Ta sử dụng PreparedStatement để xây dựng câu truy vấn (quey) lấy dữ liệu từ database dựa trên giá trị người dùng nhập vào. Nếu kết quả trả về có dữ liệu, nghĩa là thông tin hợp lệ, phương thức sẽ trả về true (ngược lại trả về false).

Bước 6: Tạo class DataConnect.java như sau:

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

Ta nạp JDBC driver bằng phương thức Class.forName() và sử dụng phương thức DriverManager.getConnection() để kết nối đến database và truyền vào các tham số url, username và password.

Bước 7: Tạo SessionUtils.java để lấy và quản lý thông tin người dùng trong session.

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

Class này giúp ta lấy session của người dùng đã đăng nhập, và từ đó có thể lấy các thông tin như userId đã được liên kết với session đó.

Bước 8: Tạo class lọc như sau:

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

	}
}

Ta đã triển khai interface lọc tiêu chuẩn bằng cách ghi đè các phương thức destroydoFilter. Trong phương thức doFilter, ta sẽ chuyển hướng người dùng về trang đăng nhập nếu họ cố gắng truy cập một trang khác mà chưa đăng nhập.

Bước 9: Tạo file admin.xhtml như sau:

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

Trang này sẽ được hiển thị khi người dùng đăng nhập thành công. Chức năng đăng xuất được thực hiện bằng cách gọi phương thức logout của class Login.java.

Bước 10: Tạo file faces-config.xml như sau:

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

Sau khi hoàn tất các bước trên, hãy chạy ứng dụng và bạn sẽ thấy các trang sau trong trình duyệt.

Trang Đăng nhập

Trang đăng nhập ứng dụng xác thực người dùng với JSF

Trang Lỗi Xác thực

Trang lỗi ứng dụng xác thực người dùng với JSF

Trang Đăng nhập Thành công

Trang đăng nhập thành công của ứng dụng xác thực người dùng với JSF

Truy cập admin.xhtml khi đã đăng nhập

Trang báo thành công trong ứng dụng xác thực người dùng với JSF

Bạn chỉ cần nhấn vào liên kết Logout, session sẽ bị vô hiệu hóa. Sau đó, nếu thử truy cập lại trang admin.xhtml, bạn sẽ được chuyển hướng về trang đăng nhập.

Tổng kết

Như bạn đã thấy JSF cho phép ta dễ dàng xây dựng cơ chế xác thực người dùng với các bước cụ thể từ quản lý phiên đến kiểm tra thông tin đăng nhập dựa trên cơ sở dữ liệu, giúp bảo vệ trang web khỏi truy cập trái phép một cách hiệu quả. Hãy tải project ví dụ ở trên từ link này để trực tiếp thử nghiệm và biết cách ứng dụng vào chính project của bạn.

0 Bình luận

Đăng nhập để thảo luận

Chuyên mục Hướng dẫn

Tổng hợp các bài viết hướng dẫn, nghiên cứu và phân tích chi tiết về kỹ thuật, các xu hướng công nghệ mới nhất dành cho lập trình viên.

Đăng ký nhận bản tin của chúng tôi

Hãy trở thành người nhận được các nội dung hữu ích của CyStack sớm nhất

Xem chính sách của chúng tôi Chính sách bảo mật.

Đăng ký nhận Newsletter

Nhận các nội dung hữu ích mới nhất