본문 바로가기

STUDY/국비과정

[JAVA 웹 개발 공부] 국비지원 59일차 - JSP DB 입출력, 에러페이지, Cookie, Session

JSP 연습 - DB 입출력

 

회원 가입 서비스
(1) index 페이지 구성(서비스 페이지 링크 포함)
(2) 입력폼(이메일, 이름, 성)
(3) 회원정보가 DB에 추가

 

*index.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>인덱스 페이지</title>
</head>
<body>
	<a href="userform.html">회원정보 추가하기</a>
</body>
</html>

 

*userform.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>회원정보 입력</title>
</head>
<body>
<form action="adduser.jsp">
	<input name="email" type="email" maxlength="60" placeholder="이메일을 입력하세요." required>
	<input name="firstname" type="text" maxlength="15" placeholder="성을 입력하세요." required>
	<input name="lastname" type="text" maxlength="15" placeholder="이름을 입력하세요." required>
	<input type="submit">
</form>
</body>
</html>

 

*adduser.jsp

<%@ page language="java" pageEncoding="UTF-8"%>
<%@page import="userinfo.UserRepository"%>
<%@page import="userinfo.UserService"%>
<%@page import="userinfo.IUserService"%>
<%
	String method = request.getMethod();
	request.setCharacterEncoding("UTF-8");

	if (method.equalsIgnoreCase("get")) {
		response.sendRedirect("error405.jsp");
	} else {
		String email = request.getParameter("email");
		String firstname = request.getParameter("firstname");
		String lastname = request.getParameter("lastname");
		
		if (email == null || firstname == null || lastname == null) {
			response.sendRedirect("error400.jsp");
		} else {
			IUserService service = new UserService(new UserRepository());
			int result = service.addUser(email, firstname, lastname);
			
			request.setAttribute("message", 
					result == 1 ? "성공적으로 추가 완료" : "추가 실패");
			request.getRequestDispatcher("/WEB-INF/result.jsp")
				.forward(request, response);
		}
	}
%>

+) 응답 코드 405 : 요청한 페이지는 있으나 동작하지 않는다.

+) request.setCharacterEncoding("UTF-8");

파라미터 값을 가져오기 전에 설정해주기(한글깨짐 해결)

 

*result.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<p><%= request.getAttribute("message") %></p>
	<a href="./index.html">인덱스로 돌아가기</a>
</body>
</html>

 

*ConnectionProvider.java

package dbutil;

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

public class ConnectionProvider {
	static {
		try {
			Class.forName("com.mysql.cj.jdbc.Driver");
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}
	public static Connection getConnection() throws SQLException {
		return DriverManager.getConnection("jdbc:mysql://localhost:3306/my_db", "root", "root");
	}
}

 

*IUserService.java

package userinfo;

public interface IUserService {
	int addUser(String email, String firstname, String lastname);
}

 

*UserService.java

package userinfo;

import java.sql.SQLException;

public class UserService implements IUserService {
	private IUserRepository repo;
	
	public UserService(IUserRepository repo) {
		this.repo = repo;
	}
	
	@Override
	public int addUser(String email, String firstname, String lastname) {
		try {
			return repo.addUser(email, firstname, lastname);
		} catch (SQLException e) {
			return 0;
		}
	}
}

 

*IUserRepository.java

package userinfo;

import java.sql.SQLException;

public interface IUserRepository {
	int addUser(String email, String firstname, String lastname) throws SQLException;
}

 

*UserRepository.java

package userinfo;

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

import dbutil.ConnectionProvider;

public class UserRepository implements IUserRepository {

	@Override
	public int addUser(String email, String firstname, String lastname) throws SQLException {
		String query = "INSERT INTO userinfo (email, firstname, lastname) VALUES (?, ? ,?)";
		try (Connection conn = ConnectionProvider.getConnection();
				PreparedStatement stmt = conn.prepareStatement(query);) {
			stmt.setString(1, email);
			stmt.setString(2, firstname);
			stmt.setString(3, lastname);
			
			return stmt.executeUpdate();
		}
	}
}

 

*error405.jsp

 

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>에러405</title>
</head>
<body>
	<% response.setStatus(405); %>
	<p>해당 메소드 방식의 요청을 수행할 수 없습니다.</p>
</body>
</html>

 

*error400.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>에러400</title>
</head>
<body>
	<% response.setStatus(400); %>
	<p>잘못된 요청입니다.</p>
</body>
</html>

 


+) 에러 페이지 forward 방식으로 적용

*adduser.jsp

<%@ page language="java" pageEncoding="UTF-8"%>
<%@page import="userinfo.UserRepository"%>
<%@page import="userinfo.UserService"%>
<%@page import="userinfo.IUserService"%>
<%
	String method = request.getMethod();
	request.setCharacterEncoding("UTF-8");

	if (method.equalsIgnoreCase("get")) {
		request.setAttribute("errorCode", 405);
		request.setAttribute("errorMessage", "지원하지 않는 방식의 요청입니다.");
		request.getRequestDispatcher("error.jsp")
			.forward(request, response);
	} else {
		String email = request.getParameter("email");
		String firstname = request.getParameter("firstname");
		String lastname = request.getParameter("lastname");
		
		if (email == null || firstname == null || lastname == null) {
			request.setAttribute("errorCode", 400);
			request.setAttribute("errorMessage", "입력형식이 올바르지 않는 형식입니다.");
			request.getRequestDispatcher("error.jsp")
			.forward(request, response);
		} else {
			IUserService service = new UserService(new UserRepository());
			int result = service.addUser(email, firstname, lastname);
			
			request.setAttribute("message", 
					result == 1 ? "성공적으로 추가 완료" : "추가 실패");
			request.getRequestDispatcher("/WEB-INF/result.jsp")
				.forward(request, response);
		}
	}
%>

*error.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>에러페이지</title>
</head>
<body>
<% 
	Integer code = (Integer) request.getAttribute("errorCode");
	String message = (String) request.getAttribute("errorMessage");
	response.setStatus(code);
%>
	<p><%= code %>에러 발생</p>
	<p>요청한 주소 : <%= request.getRequestURI() %></p>
	<p><%= message %></p>
</body>
</html>

 

Cookie(쿠키)

 

1. 쿠키

Connectionless로 인해 서버는 클라이언트를 식별할 수가 없는데, 이를 Stateless라고 합니다.

서버가 클라이언트를 기억해야 할 경우, 브라우저 단에서 쿠키라는 것을 저장하여 서버가 클라이언트를 식별할 수 있도록 한다.

쿠키 동작 방식 쿠키 생성 → 쿠키 저장 → 쿠키 전송
쿠기의 구성 이름, 값, 유효시간, 도메인, 경로
쿠키의 장점 다시 서버에 request할 필요가 없기 때문에 속도가 빠르다.
쿠키의 단점 로그인 정보 등 사용자의 정보가 저장되는 경우가 많아 보안에 취약하다.
쿠키 사용 예시 팝업 보지 않기, 사용자 이전 스크롤링이나 뷰 설정 값 등

 

2. 쿠키 생성

// 쿠키 생성
Cookie cookie = new Cookie("username", "사용자이름");

// 쿠키 값 재설정
cookie.setValue("value2");

// 쿠키 유지 시간 설정(초단위)
cookie.setMaxAge(60*2); 

// 쿠키를 클라이언트로 전송
response.addCookie(cookie);
메소드 리턴 타입 설명
getName() String 쿠키 이름을 구한다.
getValue() String 쿠키 값을 구한다.
setValue(String value) void 쿠키 값을 지정한다.
setDomain(String pattern) void 이 쿠키가 전송될 서버의 도메인을 지정한다.
getDomain() String 쿠키의 도메인을 구한다.
setPath(String url) void 쿠키의 전송할 경로를 지정한다.
getPath() String 쿠키의 전송 경로를 지정한다.
setMaxAge(int expiry) void 쿠키의 유효시간을 초 단위로 지정한다.
음수를 입력할 경우 웹 브라우저를 닫을 때 쿠키가 함께 삭제된다.
getMaxAge() int 쿠키의 유효시간을 구한다.

 

3. 쿠키 읽어오기

Cookie[] cookies = request.getCookies(); //client에서 쿠키를 받아옴

String cookieName = "";
String cookieValue = "";

if(cookies!=null){
    for(int i=0;i<cookies.length;i++){
        if(cookies[i].getName().equals("cookieName")){
            cookieName = cookies[i].getName();
            cookieValue = cookies[i].getValue();
        }
    }
}

 

4. 쿠키 삭제하기

if(cookies != null){
    for(int i=0; i < cookies.length; i++){
    	// 쿠키 유지시간은 0으로 설정
        cookies[i].setMaxAge(0);
        
        // 변경된 쿠기 정보를 다시 클라이언트에 전달
        response.addCookie(cookies[i]);
    }
}

 

5. 쿠키 이름

쿠키 이름은 콤마, 세미콜론, 공백, 등호기호('=')를 제외한 출력 가능한 아스키 문자로 구성된다. 여러 문자를 사용할 수 있지만 보통 쿠키 이름을 작성할 때에는 알파벳과 숫자만 이용한다. 쿠키 값은 콤마, 세미콜론, 공백 문자를 제외한 나머지 출력 가능한 아스키 문자를 사용할 수 있다. 값으로 사용할 수 있는 문자가 한정되어 있기 때문에 쿠키 값을 생성할 때에는 알맞은 방식으로 인코딩한다. 

// 쿠키 저장 → 인코딩
String encoded = URLEncoder.encode(str, "UTF-8");

// 쿠키 가져오기 → 디코딩
String decoded = URLDecoder.decode(str, "UTF-8");

 

6. 쿠키 유효시간

쿠키를 삭제할때 setMaxAge()를 이용해 삭제를 할 수 있다.
쿠키는 보통 유효시간을 정해주지 않으면 웹 브라우저를 닫음과 동시에 쿠키가 삭제된다.
그러나 유효시간을 정해놓으면 설정해놓은 유효시간동안 쿠키가 존재하게 되고 웹 브라우저를 닫아도 유효시간이 남아있으면 쿠키는 삭제되지 않고 남아있게 된다.

 

 

Session(세션)

 

쿠키는 사용자 정보가 브라우저에 저장되기 때문에 공격자로부터 위변조의 가능성이 높아 보안에 취약하다.

이와 달리 세션은 브라우저가 아닌 서버단에서 사용자 정보를 저장하는 구조이다.

따라서 쿠키보다는 안전하다고 할 수 있다.

그런데 세션 정보도 중간에 탈취 당할 수 있기 때문에 보안에 완벽하다고 할 수 없다.

또한 세션을 사용하면 서버에 사용자 정보를 저장하므로, 서버의 메모리를 차지하게 되고, 만약 동시 접속자 수가 많은 서비스일 경우에는 서버 과부화의 원인이 된다.

 

 

쿠키 vs 세션

 

구분 쿠키 세션
저장 위치 클라이언트 서버
저장 데이터 타입 텍스트 객체
저장 데이터 크기 제한 있음 서버에서 수용할 수 있는 만큼

 

 

JSESSIONID

 

톰캣 컨테이너에서 세션을 유지하기 위해 발급하는 키.
HTTP 프로토콜은 stateless하다. 요청시마다 새로운 연결이 생성되고 응답후 연결은 끈히게 되므로 상태를 유지할 수 없다.
따라서 상태를 저장하기 위해서 톰캣은 JSESSIONID 쿠키를 클라이언트에게 발급해주고 이 값을 통해 세션을 유지할 수 있도록 한다.

 

 

JSP 연습 - 쿠키 활용하기

 

*index.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Index</title>
</head>
<body>
	<a href="add.jsp">추가</a><br/>
	<a href="list.jsp">목록</a><br/>
	<a href="basket.jsp">장바구니 보러가기</a><br/>
	<a href="login.jsp">로그인</a><br/>
	<a href="logout.jsp">로그아웃</a><br/>
</body>
</html>

 

*login.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>로그인 페이지</title>
</head>
<body>
<%
	Cookie[] cookies = request.getCookies();
	String rememberid = "";
	for (int i = 0; i < cookies.length; i++) {
		if (cookies[i].getName().equals("remeberid")) {
			rememberid = cookies[i].getValue();
		}
	}
%>
<form action="loginprogress.jsp">
	<input name="id" type="text" placeholder="아이디"/><br>
	<input name="password" type="password" placeholder="비밀번호"/><br>
	<label><input name="rememberid" type="checkbox"/>아이디 저장</label>
	<input type="submit"/>
</form>
</body>
</html>

 

*loginprogress.jsp

<%
	String id = request.getParameter("id");
	String password = request.getParameter("password");
	String rememberid = request.getParameter("rememberid");
	
	if (id.equals("admin") && password.equals("admin")) {
		Cookie login = new Cookie("login", id);
		response.addCookie(login);
		
		if (rememberid != null) {
			Cookie cookieRemember = new Cookie("rememberid", id);
			cookieRemember.setMaxAge(60 * 60 * 24);
			response.addCookie(cookieRemember);
		}
		
		response.sendRedirect("./index.html");
	} else {
		response.sendRedirect("./login.jsp");
	}
%>

 

*logout.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>로그아웃</title>
</head>
<body>
<%
	Cookie c = new Cookie("login", "");
	c.setMaxAge(0);
	response.addCookie(c);
%>
<p>로그아웃되었습니다</p>
</body>
</html>

 

*add.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>추가 페이지</title>
</head>
<body>
<%
	Cookie[] cookies = request.getCookies();
	String value = null;
	for (int i = 0; i < cookies.length; i++) {
		if (cookies[i].getName().equals("login")) {
			value = cookies[i].getValue();
		}
	}
%>
<p><%= value %>님 안녕하세요.</p>
<p>이 페이지는 추가 페이지임</p>
</body>
</html>

 

*list.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>목록 페이지</title>
</head>
<body>
<form action="item.jsp">
	<label><input type="checkbox" name="item" value="product1"/>상품1</label>
	<label><input type="checkbox" name="item" value="product2"/>상품2</label>
	<label><input type="checkbox" name="item" value="product3"/>상품3</label>
	<label><input type="checkbox" name="item" value="product4"/>상품4</label>
	<input type="submit"/>
</form>
</body>
</html>

 

*item.jsp

<%@page import="java.net.URLEncoder"%>
<%@page import="java.util.StringJoiner"%>
<%
	String[] item = request.getParameterValues("item");
	StringJoiner sj = new StringJoiner(",");
	for (String i : item) {
		sj.add(i);
	}
	String text = sj.toString();
	String encoded = URLEncoder.encode(text, "UTF-8");
	
	Cookie cookie = new Cookie("item", encoded);
	response.addCookie(cookie);
	response.sendRedirect("./index.html");
%>

 

*basket.jsp

<%@page import="java.net.URLDecoder"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>장바구니 보기</title>
</head>
<body>
<%
	Cookie[] cookies = request.getCookies();
	Cookie item = null;
	for (int i = 0; i < cookies.length; i++) {
		if (cookies[i].getName().equals("item")) {
			item = cookies[i];
		}
	}
	
	String encoded = item.getValue();
	String text = URLDecoder.decode(encoded, "UTF-8");
	String[] split = text.split(",");
%>
<ul>
<%
	for (int i = 0; i < split.length; i++) {
		out.println("<li>" + split[i] + "</li>");
	}
%>
</ul>
<a href="">장바구니 비우기</a>
</body>
</html>