세션(Session)이란?
서버의 메모리에 정보를 저장해 놓고 필요할 때 여러 웹 페이지에서 사용할 수 있도록 하는 방법
브라우저가 최초로 서버에 접속하면 서버의 서블릿이 세션 객체를 만들고 세션 id를 브라우저에 전송한다. 브라우저는 세션 id를 jsessionId
라는 세션 쿠키로 저장한다.
브라우저가 서버에 재접속하면서 세션 쿠키에 저장된 세션 id를 서버로 전송하면 서버에서 세션 id에 따라 브라우저를 구별하여 작업을 수행할 수 있다.
HttpSession
(세션 객체) 의 메서드를 사용하기 위해서는 HttpServletResponse
의 getSession()
메서드를 호출해 객체 주소를 받아와야 한다.
HttpSession session = request.getSession();
HttpSession 클래스의 메서드
getId()
: 세션 ID(세션에 할당된 고유 식별자)를 문자열로 반환
invalidate()
: 현재 세션을 소멸시킴
isNew()
: 최초로 생성된 세션인지 기존에 생성된 세션인지 판별해 boolean으로 반환
getCreationTime()
: 세션이 생성된 시간을 long으로 반환(ms 단위)
set/getMaxInactiveInterval()
: 세션 유지 시간을 설정/반환(초 단위, 기본 설정 30분)
package sec03.ex01;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
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;
@WebServlet("/sess")
public class SessionTest extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
PrintWriter out = response.getWriter();
// 브라우저가 서버에 최초로 접속할 때 생성된 세션 객체 가져오기
HttpSession session = request.getSession();
// getId() : 세션 id 반환
out.print("세션 아이디 : "+session.getId() + "<br>");
// getCreationTime() : 세션 생성 시간을 ms단위(long)로 반환
// Date 객체로 생성해 읽을 수 있는 날짜로 바꿈
out.print("최초 세션 생성 시각 : " + new Date(session.getCreationTime()) + "<br>");
// getLastAccessedTime() : 세션이 마지막으로 접속한 시간을 ms단위로 반환
out.print("최근 세션 접근 시각 : " + new Date(session.getLastAccessedTime()) + "<br>");
// getMaxInactiveInterval() : 세션 유지 시간을 초 단위(int)로 반환
out.print("기본 세션 유효 시간 : " + session.getMaxInactiveInterval() + "초<br>");
// 세션의 유효 시간을 5초로 설정
session.setMaxInactiveInterval(5);
out.print("현재 세션 유효 시간 : " + session.getMaxInactiveInterval() + "초<br>");
// isNew() : 최초로 생성된 세션이면 true,
// 기존에 생성된 세션이면 false 반환
if(session.isNew()) {
out.print("새로 생성된 세션입니다.<br>");
} else {
out.print("기존에 생성된 세션입니다.<br>");
}
// invalidate() : 세션 소멸
session.invalidate();
}
}
💻 실행 결과
처음 접속 시와 두번째 접속 시 메세지가 다르게 출력된다. 세션 유효 시간인 5초 후에 다시 접속하면 세션 아이디가 새로 생성되고 다시 처음 접속 시 나오는 메세지가 출력된다.
파일명 : login2.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>login</title>
</head>
<body>
<form action="login" method="post" encType="utf-8">
아이디 : <input type="text" name="user_id"><br>
비밀번호 : <input type="password" name="user_pw"><br>
<input type="submit" value="로그인">
<input type="reset" value="다시 입력">
</form>
</body>
</html>
package sec03.ex04;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
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;
@WebServlet("/login")
public class SessionTest4 extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doHandle(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doHandle(request, response);
}
private void doHandle(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
PrintWriter out = response.getWriter();
// 브라우저가 서버에 최초로 접속할 때 생성된 세션 객체 가져오기
HttpSession session = request.getSession();
// login2.html 에서 입력한 값 가져오기
String user_id = request.getParameter("user_id");
String user_pw = request.getParameter("user_pw");
if(session.isNew()) {
// 세션이 최초로 생성되었을 경우, id 유효성 검사
if(user_id!=null) {
// null이 아니면 id를 세션에 바인딩
session.setAttribute("user_id", user_id);
// 같은 서블릿을 다시 요청하는 링크
out.print("<a href='login'>로그인 상태 확인</a>");
}
else {
out.print("<a href='login2.html'>다시 로그인하세요!</a>");
// 세션 삭제하기 (다시 유효성 검사하고 바인딩하기 위해)
session.invalidate();
}
}
else {
// 기존에 생성된 세션일 경우 세션에 저장된 user_id 값 가져오기
user_id = (String) session.getAttribute("user_id");
if(user_id!=null) {
out.print("안녕하세요, "+user_id+"님!");
} else {
out.print("<a href='login2.html'>다시 로그인하세요!</a>");
session.invalidate();
}
}
}
}
💻 실행 결과
아이디와 비밀번호를 입력 후 요청하면 세션의 기존 유무를 판단해 내용을 수행한다. login2.html 페이지를 거치지 않고 바로 /login으로 요청하면 세션에 저장된 user_id의 값이 null 이므로 로그인 창으로 이동하라는 메세지를 출력한다.
encodeURL(url)
: HttpServletResponse
의 메서드로, 파라미터로 작성하는 URL 뒤에 ;jsessionId=~
(세션 ID)를 붙여 문자열로 반환함, 브라우저가 쿠키를 차단해 사용할 수 없는 상황에서 쿠키 대신 사용
// 위의 SessionTest4 서블릿을 다음과 같이 수정
...
public class SessionTest4 extends HttpServlet {
private void doHandle(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
...
if(session.isNew()) {
if(user_id!=null) {
session.setAttribute("user_id", user_id);
// 원하는 url 뒤에 ;jsessionId=세션id 붙이기
String url = response.encodeURL("login");
// 같은 서블릿을 다시 요청하는 링크
out.print("<a href="+url+">로그인 상태 확인</a>");
}
...
}
💻 실행 결과
로그인 상태 확인 url에 jsessionid 값이 전송된 것을 확인할 수 있음
웹 페이지를 DB와 연동한 후 세션을 이용해 로그인 상태를 유지하는 예제
기존 실습에서 사용한 MemberDAO
, MemberDTO
클래스를 사용
파일명 : login3.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>login</title>
</head>
<body>
<form action="login" method="post" encType="utf-8">
아이디 : <input type="text" name="user_id"><br>
비밀번호 : <input type="password" name="user_pw"><br>
<input type="submit" value="로그인">
<input type="reset" value="다시 입력">
</form>
</body>
</html>
DB에 입력한 정보와 맞는 회원이 있는지 찾는 메서드를 MemberDAO
클래스에 추가
public class MemberDAO {
...
// DB에 회원 정보가 존재하는지 확인하는 메서드
public boolean isExisted(MemberDTO dto)
{
boolean result = false;
String id = dto.getId();
String pw = dto.getPwd();
try {
conn = dataFactory.getConnection();
// 레코드의 개수를 찾는 sql문 작성
// 테이블에서 특정 id, pwd를 가진 레코드의 개수를 result 컬럼의 값으로 출력
String sql = "select count(*) as result from t_member";
sql += " where id=? and pwd=?";
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, id);
pstmt.setString(2, pw);
// 검색한 결과(result 컬럼 값으로 숫자가 담긴 테이블) rs에 담기
ResultSet rs = pstmt.executeQuery();
// 커서를 첫번째 레코드로 이동
rs.next();
System.out.println("rs의 값 : "+rs.getString("result"));
// result의 값은 1 또는 0이 나옴, 해당 값을 boolean 타입으로 가져오기
result = rs.getBoolean("result");
System.out.println("result : "+result);
rs.close();
pstmt.close();
conn.close();
}
catch (Exception e) { e.printStackTrace(); }
return result;
}
}
DAO에서 회원 확인 메서드를 호출해 회원 존재 여부를 확인하고,
회원이 존재하면 세션 객체의 주소를 가져와 로그인에 필요한 데이터를 바인딩하고 로그인 성공 여부를 출력
package sec05.ex01;
import java.io.IOException;
import java.io.PrintWriter;
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;
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doHandle(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doHandle(request, response);
}
private void doHandle(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
PrintWriter out = response.getWriter();
// login3.html 에서 입력한 값 가져오기
String user_id = request.getParameter("user_id");
String user_pw = request.getParameter("user_pw");
MemberDTO dto = new MemberDTO();
dto.setId(user_id);
dto.setPwd(user_pw);
MemberDAO dao = MemberDAO.getInstance();
// dao에서 회원 정보가 존재하는지 확인하는 메서드 호출
boolean result = dao.isExisted(dto);
if(result) {
// 회원정보가 존재하면 세션 객체의 주소를 가져오고
HttpSession session = request.getSession();
// 세션에 해당 속성 설정하기
session.setAttribute("isLogon", true);
session.setAttribute("login.id", user_id);
session.setAttribute("login.pw", user_pw);
out.print("<html><body>");
out.print("안녕하세요, "+user_id+"님!<br>");
out.print("<a href='show'>회원정보 보기</a>");
out.print("</body></html>");
}
else {
out.print("<html><body><center>회원 아이디가 틀립니다.<br>");
out.print("입력한 아이디 : "+user_id+", 입력한 비밀번호 : "+user_pw+"<br>");
out.print("<a href='login3.html'>다시 로그인하기</a>");
out.print("</body></html>");
}
}
}
로그인한 상태에서 자신의 정보를 확인할 수 있는 ShowMember
서블릿 작성
package sec05.ex01;
import java.io.IOException;
import java.io.PrintWriter;
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;
@WebServlet("/show")
public class ShowMember extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doHandle(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doHandle(request, response);
}
private void doHandle(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
PrintWriter out = response.getWriter();
String id = "";
String pw = "";
// 로그인 여부를 확인하기 위한 변수
Boolean isLogon = false;
// 세션이 존재하면 세션을 반환하고, 없으면 null 반환
HttpSession session = request.getSession(false);
if(session != null) {
// 세션이 존재하면 세션의 isLogon 속성 값을 가져옴
isLogon = (Boolean) session.getAttribute("isLogon");
// 로그인 상태를 확인하기
if(isLogon == true) {
// 로그인된 id, pw 값 가져오기
id = (String)session.getAttribute("login.id");
pw = (String)session.getAttribute("login.pw");
out.print("<html><body>");
out.print("아이디 : "+id+"<br>");
out.print("비밀번호 : "+pw+"<br>");
out.print("</body></html>");
}
else {
// 로그인 상태가 아니면 로그인 창으로 이동
response.sendRedirect("login3.html");
}
}
else {
// 세션이 생성되지 않았으면 로그인 창으로 이동
response.sendRedirect("login3.html");
}
}
}
💻 실행 결과
DB에서 회원 정보를 조회하고 로그인 정보를 세션에 바인딩해 로그인 상태를 계속 유지하는 것을 확인 가능, 로그인 페이지를 거치지 않고 /show url로 접근하면 로그인 페이지로 redirect됨