컴퓨터/WEB

[Spring] Servlet, JSP 그리고 세션을 이용한 로그인, 로그아웃 구현

정석이 2022. 9. 25. 20:54

 

저번 글 : https://ticssfm.tistory.com/177?category=1007516

 

[Backend] Servlet, JSP 그리고 MVC 패턴

Servlet / JSP 서블릿/JSP는 자바를 사용해 동적인 웹을 만들기 위해 사용되는 프로그래밍 기술이다. 정적 웹 페이지는 미리 저장된 파일을 요청에 따라 걍 보내는거고, 동적 웹 페이지는 서버에 있

ticssfm.tistory.com

 

 

 

 

저번 글에 이어서 이번에는 MVC 패턴을 이용하여 간단하게 로그인, 로그아웃하는 법을 포스팅 하겠다.

 

 

 

일단 User 정보가 들어갈 DB는 mysql을 사용하였다. DB 먼저 생성해주자

 

 

create schema study;
use study;
create table `user`(
    `id` varchar(50) primary key,
    `pwd` varchar(50) not null
);

desc user; -- user table 정보 확인
insert into user(id, pwd) values ("gd", "gd");
select * from user; -- user table data 확인

 

 

이렇게 study DB에 user 테이블을 만들고 간단하게 id, pwd만 넣을 수 있게 만들었다.

 

 

그럼 이제 dynamic web 프로젝트를 생성해서 만들어보자! 참고로 톰캣은 9.0버전 사용했다.

 

 

 

 


MVC 패턴을 이용한 로그인, 로그아웃 구현

 

 

0. DBUtil 클래스 생성

package com.study.sample.util;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class DBUtil {

	private DBUtil() {
		try {
			Class.forName("com.mysql.cj.jdbc.Driver"); // mysql 드라이버 로드
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}
    // 싱글톤
	private static DBUtil instance = new DBUtil();
	public static DBUtil getInstance() {
		return instance;
	}
	
	public Connection getConnection() throws SQLException {
		String url = "jdbc:mysql://127.0.0.1:3306/study?serverTimezone=UTC&useUniCode=yes&characterEncoding=UTF-8";
		String user = "ID"; // DB id
		String pwd = "PWD";  // DB pwd
		return DriverManager.getConnection(url, user, pwd); // load된 드라이버로 Connection 활성화
	}
	
	public void close(AutoCloseable... closeables) {
		for (AutoCloseable c : closeables) {
			if (c != null) {
				try {
					c.close();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
	}
	
}

 

DB 연동을 위해 DBUtil이라는 클래스를 싱글톤으로 생성해주었다.

 

JDBC 인터페이스를 이용해 mysql과 연동해주었다.

 

 

 

1. DTO

package com.study.sample.dto;

public class User {
	String id, pwd;

	public User() {
		super();
		// TODO Auto-generated constructor stub
	}

	public User(String id, String pwd) {
		super();
		this.id = id;
		this.pwd = pwd;
	}

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

	@Override
	public String toString() {
		return "User [id=" + id + ", pwd=" + pwd + "]";
	}
}

 

 

 

DTO는 Data Transfer Object의 약자로, 데이터 전송을 위해 생성되는 객체이다.

 

table에 있는 id, pwd 값을 사용하기 위한 객체를 생성해주었다.

 

 

 

 

2. DAO

package com.study.sample.dao;

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

import com.study.sample.dto.User;
import com.study.sample.util.DBUtil;

public class UserDao {
	
	// 싱글톤
	private UserDao () {}
	private static UserDao instance = new UserDao();
	public static UserDao getInstance() {
		return instance;
	}

	DBUtil dbUtil = DBUtil.getInstance();
	
	// 로그인
	public User login(String id, String pwd) throws SQLException {
		String sql = "select id, pwd from user where id=? and pwd=?";
		Connection conn = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		
		try {
			conn = dbUtil.getConnection(); // DB 연결
			pstmt = conn.prepareStatement(sql); // sql 실행
			
			pstmt.setString(1, id);
			pstmt.setString(2, pwd);
			
			rs = pstmt.executeQuery(); // sql문을 executeQuery() 메소드를 사용해 테이블로 받아온다.
			
			if(rs.next()) { // 만약 rs 테이블이 존재한다면 user에 넣어서 리턴한다.
				User user = new User();
				user.setId(rs.getString(1));
				user.setPwd(rs.getString(2));
				
				return user;
			}
			return null;

			
		} finally {
			dbUtil.close(pstmt, conn);
			
		}
	}
}

 

 

다음은 Dao 부분이다. 

 

DAO는 Data Access Object의 약자로, 실제 DB에 접근하는 객체이다.

 

이 부분이 MVC에서 Model 부분이다.

 

그리고 Model은 컨트롤러에서 바로 넘어오지 않고 Service를 거쳐서 온다.

서비스에서 여러가지 처리도 가능

 

참고로 login 리턴 타입을 User로 해주었는데 int나 boolean 등으로 해도 된다.

 

 

참고 이미지 : https://hyuntaekhong.github.io/til/TIL-200824/

 

 

 

3. Service

package com.study.sample.service;

import java.sql.SQLException;

import com.study.sample.dao.UserDao;
import com.study.sample.dto.User;

public class UserService {

	// 싱글톤
	private UserService () {}
	private static UserService instance = new UserService();
	public static UserService getInstance() {
		return instance;
	}
	
	UserDao userDao = UserDao.getInstance();
	
	// 로그인
	public User login(String id, String pwd) throws SQLException {
		return userDao.login(id, pwd);
	}
}

 

다음은 Service 클래스이다.

 

컨트롤러에서 바로 DAO에 접근하지 않고 Service를 거쳐서 들어온다.

 

 

 

4. Controller

package com.study.sample.controller;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import com.mysql.cj.Session;
import com.study.sample.dto.User;
import com.study.sample.service.UserService;

@WebServlet("/user")
public class UserController extends HttpServlet {
	private static final long serialVersionUID = 1L;
	
	UserService userService = UserService.getInstance();

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String action = request.getParameter("action");
		
		try {
			switch (action) {
			case "login":
				login(request, response);
				break;
			case "logout":
				logout(request, response);
				break;

			default:
				break;
			}
			
			
		} catch (Exception e) {
			response.sendRedirect(request.getContextPath() + "/error/error.jsp");
			e.printStackTrace();
		}
		
	}

	private void logout(HttpServletRequest request, HttpServletResponse response) {
		HttpSession session = request.getSession();
		session.removeAttribute("id");
		
	}

	private void login(HttpServletRequest request, HttpServletResponse response) throws IOException {
		String id = request.getParameter("id");
		String pwd = request.getParameter("pwd");
		
		try {
			User user = userService.login(id, pwd); // service -> DAO에서 보낸 User 받아오기
			
			HttpSession session = request.getSession();
			session.setAttribute("id", id); // 세션에 id 저장
			
			request.setAttribute("info", user); // loginSuccess.jsp로 가면서 user를 info라는 이름으로 보냄
			
			request.getRequestDispatcher("/loginSuccess.jsp").forward(request, response);
			
		} catch (Exception e) {
			response.sendRedirect(request.getContextPath() + "/error/error.jsp");
			e.printStackTrace();
		}
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response);
	}

}

 

 

드디어 view에서 바로 넘어오는 controller이다.

 

로그아웃은 DB를 거칠 필요가 없으므로 컨트롤러에서 처리해주었다.

 

로그인 시 sessoin에 id값을 저장하고 로그아웃 클릭 시 session에 있는 id 데이터를 삭제한다.

 

view인 jsp에서 action=login을 호출하면 controller에 있는 login() 메소드를 호출하는 방식으로 구현하였다.

 

 

 

5. view

 

login.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<c:set var="root" value="${pageContext.request.contextPath}" />

<!DOCTYPE html>
<html>
<head>
</head>
<body>

	<form action="${root}/user">
	<input type="hidden" name="action" value="login">
	<div class="form-group">
	      <label for="productCode">id</label>
	      <input type="text" class="form-control" id="id" name="id" placeholder="ID 입력">
	    </div>
	    <div class="form-group">
	      <label for="model">password</label>
	      <input type="text" class="form-control" id="pwd" name="pwd" placeholder="PWD 입력">
	    </div>

	    <button type="submit" class="btn btn-primary" id="login">로그인</button>
	    <a class="btn btn-secondary" href="${root}/product?action=list" >취소</a>
	  </form>
	

</body>

 

login에 필요한 id 와 pwd를 입력받는 input을 만들고 로그인버튼 클릭 시 GET방식으로 넘겨주었다.

 

 

 

loginSuccess.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<c:set var="root" value="${pageContext.request.contextPath}" />
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<h1>로그인</h1>
	<c:choose>
		<c:when test="${info.id ne null}">
			<h1>성공!</h1>
			${info.id} <br>
			${info.pwd}
		</c:when>
		<c:otherwise>
			<h1>실패</h1>
		</c:otherwise>

	</c:choose>

</body>
</html>

 

 

로그인이 되었는지 확인하기 위해 간단하게 el태그를 사용해 controller에서 넘겨준 id값이 null이 아니라면

성공! 과 아이디, 비밀번호를 출력하는 화면이다.

 

 

 

 

- 결과 화면

 

로그인 화면

 

로그인 성공 화면

 

 

로그인 실패 화면