인증 메커니즘을 사용하여 사용자는 사용자 이름과 암호를 검증하여 응용 프로그램에 안전한 액세스 권한을 얻을 수 있습니다. 로그인에는 JSF 뷰, DAO 객체, HttpSession을 사용하여 세션 관리, JSF 관리 빈 및 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를 기본 키로 사용하여 사용자 테이블을 만들고, 사용자 이름 및 암호 필드에는 null을 허용하지 않는 제약 조건이 있습니다. 단계 2: Users 테이블에 데이터를 삽입합니다;
INSERT INTO Users VALUES(1,'adam','adam');
프로젝트 관련 코드로 넘어가기 전에 Eclipse에서 프로젝트 구조를 보여주는 이미지가 아래에 표시됩니다. 동적 웹 프로젝트를 만들고 프로젝트 스텁을 얻기 위해 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 로그인 뷰 페이지를 만들고, 이러한 필드에 값을 로그인 관리 빈을 통해 설정합니다. 로그인 버튼을 클릭하면 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";
}
}
우리는 사용자 이름, 비밀번호 및 오류 메시지 필드를 위해 사용자, pwd 및 msg 세 개의 문자열 변수를 선언하고 getter 및 setter 메서드를 작성합니다. 사용자 이름과 비밀번호 필드를 유효성 검사하기 위해 LoginDAO
클래스를 호출하여 데이터베이스에서 사용자 이름과 비밀번호를 가져와 프론트 엔드 값과 비교하는 validateUsernamePassword()
메서드를 작성합니다. 사용자 이름과 비밀번호가 일치하지 않으면 “잘못된 사용자 이름 및 비밀번호”라는 오류 메시지가 표시됩니다. 또한 로그아웃을 수행하기 위해 HTTPSession을 무효화하는 logout()
메서드도 작성됩니다. 단계 5: 이제 다음과 같이 LoginDAO java 클래스를 생성합니다. 데이터베이스 작업 코드가 실제 프로젝트에서 사용하기에 최적화되지 않았음을 유의하십시오. 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;
}
}
validate()
메서드에서는 먼저 DataConnect
클래스의 getConnection
메서드를 호출하여 데이터베이스에 연결을 설정합니다. PreparedStatement
을 사용하여 사용자가 입력한 값으로 데이터베이스에서 데이터를 가져오는 쿼리를 작성합니다. 결과 세트에서 데이터를 가져오면 입력이 유효하다는 의미이므로 true를 반환하고, 그렇지 않으면 false를 반환합니다. 단계 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) {
}
}
}
우리는 Class.forName
메서드를 사용하여 JDBC 드라이버를 로드하고, DriverManager.getConnection
메서드를 사용하여 데이터베이스에 연결하기 위해 url, 사용자 이름 및 비밀번호를 전달합니다. 단계 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 메서드를 통해 각 사용자에 대한 세션을 얻어 세션 ID를 특정 사용자 ID에 연결합니다. 단계 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>
이 페이지는 사용자가 성공적으로 로그인한 경우에 렌더링됩니다. 로그아웃 기능은 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>
모든 위에 지정된 단계를 완료한 후 응용 프로그램을 실행하고 브라우저에서 다음 출력을 확인하십시오. 로그인 페이지 인증 오류 페이지
로그인 성공 페이지
로그인한 상태에서 admin.xhtml에 액세스
로그아웃 링크를 클릭하면 세션이 무효화되며 그 후에 admin.xhtml 페이지에 액세스하려고하면 로그인 페이지로 리디렉션됩니다. 아래 링크에서 프로젝트를 다운로드하고 시도해보세요.
Source:
https://www.digitalocean.com/community/tutorials/jsf-authentication-login-logout-database-example