국비교육(22-23)

31일차(1)/jsp(11) : 회원가입, 로그인 기능 구현하기

서리/Seori 2022. 11. 21. 15:36

31일차(2)/jsp(12) : 회원가입, 로그인 기능 구현하기

 

Step04_Final 프로젝트 생성

 

- 회원가입, 로그인, 로그아웃 기능을 만들 예정!
- 회원정보 테이블을 오라클에서 만들 수도 있지만,
  이클립스에 추가기능을설치해서 이클립스에서 DB를 제어하도록 할 수 있다.

 

- java EE환경에서 new jsp파일 생성!

 

<index.jsp>

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>    
<%
	//session scope에 id라는 키값으로 저장된 값이 있는지 읽어와 본다.(없으면 null)
	String id=(String)session.getAttribute("id");
	
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>/index.jsp</title>
</head>
<body>
	<div class="container">
		<%if(id != null) {%>
			<p>
				<strong><%=id %></strong>님 로그인중....
				<a href="${pageContext.request.contextPath }/users/logout.jsp">로그아웃</a>
			</p>
		<%}else{ %>
			<a href="${pageContext.request.contextPath }/users/loginform.jsp">로그인</a>
		<%} %>
		<h1>인덱스 페이지입니다.</h1>
		<ul>
			<li><a href="${pageContext.request.contextPath }/users/signup_form.jsp">회원가입</a></li>		
		</ul>
	</div>
</body>
</html>

 

 

 

- /users/ <signup_form.jsp> 생성!

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>/users/signup_form.jsp</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-Zenh87qX5JnK2Jl0vWa8Ck2rdkQ2Bzep5IDxbcnCeuOxjzrPF/et3URy9Bv1WTRi" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-OERcA2EqjJCMA+/3y+gxIOqMEjwtxJY7qPCqsdltbNJuaOe923+mo//f6V8Qbsw3" crossorigin="anonymous"></script>
</head>
<body>
	<div class="container">
		<h1>회원 가입 폼입니다.</h1>
		<form action="signup.jsp" method="post">
			<div>
			 	<label for="id" class="control-label">아이디</label>
			 	<input type="text" class="form-control" name="id" id="id" />
			</div>
			<div>
				<label for="pwd" class="control-label">비밀번호</label>
				<input type="text" class="form-control" name="pwd" id="pwd" />
			</div>
			<div>
				<label for="email" class="control-label">이메일</label>
				<input type="text" class="form-control" name="email" id="email" />
			</div>	
			<button class="btn btn-outline-primary" type="submit">가입</button>			
		</form>
	</div>
</body>
</html>

 

 

*DB 연결하기 위한 세팅 필요

 

- Step02에서 test.util 패키지째로 DbcpBean 복사하기

 

- Step04 프로젝트에도 web.xml 을 만들어주고,

  Step02 프로젝트 web.xml 에서 --DB 접속 설정-- 복사해오기

 

- lib 안에도 ojdbc6.jar파일을 넣어준다.

 

 

- DTO, DAO 만들기

test.users.dto / test.users.dao 패키지 생성-클래스 생성

 

<UsersDto>

package test.users.dto;

public class UsersDto {
	private String id;
	private String pwd;
	private String email;
	private String profile;
	private String regdate;
	
	public UsersDto() {}

	public UsersDto(String id, String pwd, String email, String profile, String regdate) {
		super();
		this.id = id;
		this.pwd = pwd;
		this.email = email;
		this.profile = profile;
		this.regdate = regdate;
	}

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public String getPwd() {
		return pwd;
	}

	public void setPwd(String pwd) {
		this.pwd = pwd;
	}

	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	public String getProfile() {
		return profile;
	}

	public void setProfile(String profile) {
		this.profile = profile;
	}

	public String getRegdate() {
		return regdate;
	}

	public void setRegdate(String regdate) {
		this.regdate = regdate;
	}	
}

 

 

<UsersDao>

package test.users.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

import test.users.dto.UsersDto;
import test.util.DbcpBean;

public class UsersDao {
	private static UsersDao dao;
	//외부에서 객체 생성할 수 없도록
	private UsersDao() {}
	//참조값을 리턴해주는 static 메소드
	public static UsersDao getInstance() {
		if(dao==null) {
			dao=new UsersDao();
		}
		return dao;
	}
		
	//인자로 전달되는 dto에 있는 아이디와 비밀번호를 이용해서 해당 정보가 유효한 정보인지 여부를 리턴하는 메소드
	public boolean isValid(UsersDto dto) {
		
		//아이디 비밀번호 유효성 여부를 담을 변수를 만들고 초기값 false 부여하기
		boolean isValid=false;
		
		Connection conn = null;
		PreparedStatement pstmt = null;		
		ResultSet rs=null;
		try {
			//Connection Pool에서 Connection 객체를 하나 얻어온다.
			conn = new DbcpBean().getConn();
			//실행할 sql문의 뼈대 구성하기
			String sql = "SELECT * FROM users"
					+ " WHERE id=? AND pwd=?";
			//sql문의 ?에 바인딩할게 있으면 한다.			
			pstmt = conn.prepareStatement(sql);
			pstmt.setString(1, dto.getId());
			pstmt.setString(2, dto.getPwd());
			//SELECT문을 수행하고 결과값을 받아온다.
			rs=pstmt.executeQuery();
			//SELECT된 ROW가 있는지 확인해본다.
			if (rs.next()) {
				//select된 row가 있다면 유효한 정보가 맞다.
				isValid=true;
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if (rs != null)
					rs.close();
				if (pstmt != null)
					pstmt.close();
				if (conn != null)
					conn.close(); //Connection Pool에 Connection 반납하기

			} catch (Exception e2) {
			}
		}
		return isValid;
	}	
	
	//회원 한명의 정보를 DB에 저장하고 성공여부를 리턴하는 메소드
	public boolean insert(UsersDto dto) {//UsersDto에 id, pwd, email이 있다.
		Connection conn = null;
		PreparedStatement pstmt = null;
		int rowCount = 0;
		try {
			conn = new DbcpBean().getConn();
			String sql = "INSERT INTO users"
					+ " (id, pwd, email, regdate)"
					+ " VALUES(?, ?, ?, sysdate)";
			pstmt = conn.prepareStatement(sql);
			//?에 바인딩
			pstmt.setString(1, dto.getId());
			pstmt.setString(2, dto.getPwd());
			pstmt.setString(3, dto.getEmail());
			//INSERT or UPDATE or DELETE문을 수행하고 수정,삭제,추가된 row의 개수 리턴
			rowCount = pstmt.executeUpdate();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if (pstmt != null)
					pstmt.close();
				if (conn != null)
					conn.close();
			} catch (Exception e2) {
			}
		}

		if (rowCount > 0) {
			return true;
		} else {
			return false;
		}		
	}	
}

 

 

<signup_form.jsp>

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>/users/signup_form.jsp</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-Zenh87qX5JnK2Jl0vWa8Ck2rdkQ2Bzep5IDxbcnCeuOxjzrPF/et3URy9Bv1WTRi" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-OERcA2EqjJCMA+/3y+gxIOqMEjwtxJY7qPCqsdltbNJuaOe923+mo//f6V8Qbsw3" crossorigin="anonymous"></script>
</head>
<body>
	<div class="container">
		<h1>회원 가입 폼입니다.</h1>
		<form action="signup.jsp" method="post">
			<div>
			 	<label for="id" class="control-label">아이디</label>
			 	<input type="text" class="form-control" name="id" id="id" />
			</div>
			<div>
				<label for="pwd" class="control-label">비밀번호</label>
				<input type="text" class="form-control" name="pwd" id="pwd" />
			</div>
			<div>
				<label for="email" class="control-label">이메일</label>
				<input type="text" class="form-control" name="email" id="email" />
			</div>	
			<button class="btn btn-outline-primary" type="submit">가입</button>			
		</form>
	</div>
</body>
</html>

 

- 폼으로 id pwd email 값을 받아서 저장!

 

- 연결되는 signup.jsp생성 필요

 

<signup.jsp>

<%@page import="test.users.dto.UsersDto"%>
<%@page import="test.users.dao.UsersDao"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
	//1. 폼 전송되는 아이디, 비밀번호, 이메일 주소를 읽어온다.
	request.setCharacterEncoding("utf-8");
	String id=request.getParameter("id");
	String pwd=request.getParameter("pwd");
	String email=request.getParameter("email");	
	//2. UsersDto에 담는다.
	UsersDto dto= new UsersDto();
	dto.setId(id);
	dto.setPwd(pwd);
	dto.setEmail(email);	
	//3. UsersDao를 이용해서 DB에 저장하고
	boolean isSuccess=UsersDao.getInstance().insert(dto);	
	//4. 결과를 응답한다.
	
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>/users/signup.jsp</title>
</head>
<body>
	<div class="container">
	<%if(isSuccess){ %>
		<p>
			<strong><%=id %></strong> 님 가입되었습니다.
			<a href="loginform.jsp">로그인 하러 가기</a>
		</p>
	<%} else{%>
		<p>
			가입에 실패했습니다.
			<a href="signup_form.jsp">다시 가입하러 가기</a>
		</p>
	<%} %>
	</div>
</body>
</html>

 

- 서버가 입력받은 내용을 원활하게 읽어오기 위해서는

 signup_from의 label name 속성의 value

 signup의 .getParameter()에 들어가는 값이 반드시 일치해야 한다.

 

- 회원가입 된다. Quantum DB에 들어가서도 확인할 수 있다.

 

 

<loginform.jsp>

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>/users/loginform.jsp</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-Zenh87qX5JnK2Jl0vWa8Ck2rdkQ2Bzep5IDxbcnCeuOxjzrPF/et3URy9Bv1WTRi" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-OERcA2EqjJCMA+/3y+gxIOqMEjwtxJY7qPCqsdltbNJuaOe923+mo//f6V8Qbsw3" crossorigin="anonymous"></script>
</head>
<body>
	<div class="container">
		<h1>로그인 폼</h1>
		<form action="login.jsp" method="post">
			<div>
				<label for="id" class="form-label">아이디</label>
				<input type="text" name="id" id="id" class="form-control" />
			</div>
			<div>
				<label for="pwd" class="form-label">비밀번호</label>
				<input type="password" name="pwd" id="pwd" class="form-control" />
			</div>
			<button class="btn btn-primary" type="submit">로그인</button>
		</form>
	</div>
</body>
</html>

 

- UserDao에 id와 pwd가 일치하는 row를 찾는 메소드를 만들어야 한다.

- 폼에 입력되는 값과 비교하여 select 되는 row가 있는지 찾는다.

- and 조건으로 묶으면 id, pwd 둘다 맞아야만 row를 찾을 수 있다. 둘중  하나라도 다르면 로그인 불가!

 

- 찾은 값이 있으면(유효한 정보이면) session scope에 저장한다.

- '해당 정보가 유효한 정보인지' == 'DB에 해당 정보가 존재하는지' 를 의미한다.

 

 

<UsersDao>에 select문 추가

//인자로 전달되는 dto에 있는 아이디와 비밀번호를 이용해서 해당 정보가 유효한 정보인지 여부를 리턴하는 메소드
public boolean isValid(UsersDto dto) {

    //아이디 비밀번호 유효성 여부를 담을 변수를 만들고 초기값 false 부여하기
    boolean isValid=false;

    Connection conn = null;
    PreparedStatement pstmt = null;		
    ResultSet rs=null;
    try {
        //Connection Pool에서 Connection 객체를 하나 얻어온다.
        conn = new DbcpBean().getConn();
        //실행할 sql문의 뼈대 구성하기
        String sql = "SELECT * FROM users"
                + " WHERE id=? AND pwd=?";
        //sql문의 ?에 바인딩할게 있으면 한다.			
        pstmt = conn.prepareStatement(sql);
        pstmt.setString(1, dto.getId());
        pstmt.setString(2, dto.getPwd());
        //SELECT문을 수행하고 결과값을 받아온다.
        rs=pstmt.executeQuery();
        //SELECT된 ROW가 있는지 확인해본다.
        if (rs.next()) {
            //select된 row가 있다면 유효한 정보가 맞다.
            isValid=true;
        }
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        try {
            if (rs != null)
                rs.close();
            if (pstmt != null)
                pstmt.close();
            if (conn != null)
                conn.close(); //Connection Pool에 Connection 반납하기

        } catch (Exception e2) {
        }
    }
    return isValid;
}

 

SELECT * FROM users 

WHERE id='banana' AND pwd='1234' 

- DB에서 찾아서 T/F값을 반환한다. oracle에서 위와 같이 sql문을 작성한 것과 같다.

  저 값이 있으면 true를 반환하고, 없으면 false를 반환하는 것!

 

- select될 row가 많아야 1개이기 때문에 while문 대신 if문을 쓴다.

 (반복문을 돌면서 rs에 목록을 담지 않아도 된다)

 

- if문 안에 isValid=true 로 바뀌는 값을 넣을 것이므로 위에서 isValid 변수를 미리 만들어준다.

 

- 먼저 초기값 false를 부여하고, 특정 조건일 경우 true로 바뀌도록 설정한다.

 

 

<login.jsp> 로그인할 페이지 추가

<%@page import="test.users.dto.UsersDto"%>
<%@page import="test.users.dao.UsersDao"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
   
<%
	//1. 폼 전송하는 아이디, 비밀번호 읽어오기
	request.setCharacterEncoding("utf-8");
	String id=request.getParameter("id");
	String pwd=request.getParameter("pwd");	
	UsersDto dto=new UsersDto();
	dto.setId(id);
	dto.setPwd(pwd);
	//2. DB에 실제로 존재하는 맞는 정보인지 확인한다.(맞는 정보이면 로그인 처리도 한다.)
	boolean isValid=UsersDao.getInstance().isValid(dto);	
	if(isValid){
		//session scope에 id라는 키값으로 로그인된 아이디 담기
		session.setAttribute("id", id);
	}
	//3. 응답
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>/users/login.jsp</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-Zenh87qX5JnK2Jl0vWa8Ck2rdkQ2Bzep5IDxbcnCeuOxjzrPF/et3URy9Bv1WTRi" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-OERcA2EqjJCMA+/3y+gxIOqMEjwtxJY7qPCqsdltbNJuaOe923+mo//f6V8Qbsw3" crossorigin="anonymous"></script>
</head>
<body>
	<div class="container">
		<% if(isValid){ %>		
			<p class="alert alert-success">		
				<strong><%=id %></strong> 회원님 로그인되었습니다.			
				<a href="../index.jsp">인덱스로 이동하기</a>
			</p>
		<%}else{ %>
			<p class="alert alert-danger">		 
				로그인에 실패했습니다.	
				<a href="loginform.jsp">다시 로그인하기</a>
			</p>
		<%} %>
	</div>
</body>
</html>

 

- if문 안에 session을 추가해서 정보가 맞을 경우 로그인 처리되도록 한다.

 

- .setMaxInactiveInterval() : 기본값은 30분이다!

- bootstrap을 추가해주었다.

 

<div class="container">
    <%if(id != null) {%>
        <p>
            <strong><%=id %></strong>님 로그인중....
            <a href="${pageContext.request.contextPath }/users/logout.jsp">로그아웃</a>
        </p>
    <%}else{ %>
        <a href="${pageContext.request.contextPath }/users/loginform.jsp">로그인</a>
    <%} %>
</div>

- index 에 로그인 id를 읽어와 로그인 여부에 따라 페이지가 다르게 보이도록 한다.

 

 

 

<logout.jsp>

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>/users/logout.jsp</title>
</head>
<body>
<%
	session.removeAttribute("id"); 
%>
	<script>
		alert("정상적으로 로그아웃 되었습니다.");
		location.href="${pageContext.request.contextPath }/index.jsp";
	</script>
</body>
</html>

 

- session.removeAttribute("id"); 로 작성하면 세션에 저장된 해당 id가 로그아웃 되는 것.

  session.invalidate(); 로 작성해서 세션을 초기화해도 된다!

 

- 로그아웃하면 알림창이 뜨고, 확인을 누르면 인덱스로 이동하도록 설정