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>
完成上面指定的所有步骤后,运行应用程序