JSF身份验证登录注销数据库示例
身份验证机制允许用户通过验证用户名和密码来安全访问应用程序。
我们将使用JSF视图进行登录,使用DAO对象,使用HttpSession进行会话管理,使用JSF管理的bean和mysql数据库。
现在让我们详细了解如何在JSF应用程序中创建JSF登录注销身份验证机制。
步骤1:在mysql数据库中创建表Users
CREATE TABLE Users( uid int(20) NOT NULL AUTO_INCREMENT, uname VARCHAR(60) NOT NULL, password VARCHAR(60) NOT NULL, PRIMARY KEY(uid));
其中我们以uid作为主键,用户名和密码字段(不具有空约束)创建用户表。
步骤2:将数据插入表Users as;
INSERT INTO Users VALUES(1,'adam','adam');
在继续进行与项目相关的代码之前,下图显示了Eclipse中的项目结构。
只需创建一个动态Web项目并将其转换为Maven即可获得项目存根,然后继续添加其他组件。
步骤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登录视图页面,并通过登录托管bean为这些字段设置值。
我们在单击登录按钮时调用validateUsernamePassword方法来验证用户名和密码。
第4步:创建托管beanLogin.java。
package com.theitroad.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.theitroad.jsf.dao.LoginDAO;
import com.theitroad.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";
}
}
我们为用户名,密码和错误消息字段以及getter和setter方法声明三个String变量user,pwd和msg。
我们通过调用LoginDAO类从数据库中获取用户名和密码,并将其与传递的前端值进行比较,从而编写一种方法ValidateUsernamePassword()来验证用户名和密码字段。
如果用户名和密码不匹配,则会显示一条错误消息"错误的用户名和密码"。
还编写了一个logout()方法来通过使附加的HTTPSession无效来执行注销。
步骤5:现在,如下所示创建LoginDAO Java类。
请注意,数据库操作代码并未针对在实际项目中使用而进行优化,因此我之所以尽快编写它,是因为其思想是在JSF应用程序中学习身份验证。
package com.theitroad.jsf.dao;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import com.theitroad.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;
}
}
在validate()方法中,我们首先通过调用DataConnect类的getConnection方法来建立与数据库的连接。
我们使用PreparedStatement构建查询,以使用用户输入的值从数据库中获取数据。
如果在结果集中获得任何数据,则表示输入有效,并且返回true,否则返回false。
第6步:将DataConnect.java类创建为;
package com.theitroad.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", "hyman", "hyman123");
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) {
}
}
}
我们使用Class.forName方法加载JDBC驱动程序,并使用传递URL,用户名和密码的DriverManager.getConnection方法来连接数据库。
步骤7:创建SessionUtils.java以获取和管理与会话相关的用户信息。
package com.theitroad.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方法登录的每个用户获得一个会话,从而将会话ID与特定用户ID相关联。
步骤8:将授权过滤器类创建为;
package com.theitroad.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>
用户成功登录后将显示此页面。
注销功能是通过调用Login.java类的logout方法实现的。
步骤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>
完成上面指定的所有步骤后,运行应用程序

