Session

  • 세션은 서로 관련된 요청들을 하나로 묶은 것

  • 쿠키를 이용한다

  • 브라우저마다 개별 저장소(세션 객체)를 서버에서 제공한다

  • 쿠키는 브라우저에 저장, 세션은 서버에 저장

  • 원래 요청들은 서로 독립적

  • 브라우저가 요청을 보내면 서버는 응답헤더에 세션 id를 쿠키에 저장해서 응답한다

  • 그 다음부터는 요청에 쿠키가 자동으로 따라 간다

  • 다음 요청부터 서버는 요청의 쿠키를 보고 같은 세션 id를 갖는 저장소를 사용한다

세션 동작 과정

  1. 처음 세션 객체가 생성될 때 서버는 응답 헤더 쿠키에 생성한 세션 id를 남긴다
  2. 다음부터 브라우저가 서버에 요청을 보내면 요청 정보에서 세션을 읽어 해당 저장소를 사용한다
HttpSession session = request.getSession();
  1. 저장소에 값을 key, value 형태로 저장할 수 있다
session.serAttribute("id", "asdf");

세션과 관련된 메서드

(아래 메서드는 pageContext, request, session, application에서 공통으로 사용하는 메서드)

세션 종료

  1. 수동종료
HttpSession session = request.getSession();
session.invalidate();					// 1. 즉시 종료
session.setMaxInactiveInterval(30*60); // 2. 예약종료 (초단위, 30분 후)
  1. 자동종료 - web.xml에서 설정
<session-config>
  <session-timeout>30</session-timeout> //분단위
</session-config>

쿠키와 세션 비교

쿠키

  • 브라우저에 저장
  • 서버 부담x
  • 보안에 불리
  • 서버 다중화에 유리

세션

  • 서버에 저장
  • 서버 부담o
  • 보안에 유리
  • 서버 다중화에 불리
  • 서버 다중화
    서버가 한 대 뒤에 여러 대가 연결되어 있는 서버 다중화 상태의 경우
    요청이 오면 맨 앞 한 대가 요청을 받아 변환하고 다른 서버들로 분산한다
    쿠키의 경우 브라우저에 id정보가 저장되어 있기 때문에 어느 서버에 가도 같은 상태를 유지하는데
    세션의 경우 서버마다 다른 id의 세션이 생겨서 이를 동기화해주어야 한다

쿠키 허용 여부에 따른 세션

  • 첫 요청을 보내면 요청 헤더에는 세션 id가 없고 응답에서 쿠키를 만들라는 요청과 함께 받는다
  • 두 번째 요청부터는 쿠키에 저장되어 세션 id를 함께 보내게 된다
  1. 만약 쿠키를 허용하지 않는다면
    아무리 요청해도 서버는 쿠키에 세션을 저장해서 계속해서 보내고 있는데
    브라우저가 쿠키를 생성하지 않으니 세션도 저장되지 않아서 요청을 보낼 때마다 서버는 새로운 세션을 생성한다
  • 서버는 브라우저가 쿠키를 허용하지 않은 상황을 대비해야 한다
    그래서 쿠키를 허용하지 않는 브라우저가 있을 수도 있기 때문에 세션을 저장하고 싶다면 url에 세션을 저장하도록 추가한다
<c:url value="/../"/>
  • 첫 요청은 세션이 없고 응답은 쿠키를 만들라는 헤더와 함께 세션 아이디가 들어오고 url에 세션 아이디를 붙여준다.
    하지만 쿠키는 만들어지지 않고 들어온 세션 아이디가 다음 요청부터 url에 함께 전송되게 된다
  1. 쿠키가 허용되었다면
    첫 요청은 세션이 없고 응답은 쿠키를 만들라는 헤더와 함께 세션 아이디가 들어오고url에 세션 아이디를 붙여준다.
    하지만 쿠키가 생성되었기 때문에 두 번째 요청부터는 url에 세션 아이디가 붙지 않는다

세션 실습

  1. BoardController.java를 만든다
    board의 주소를 요청하면 board 뷰를 반환하도록
public class BoardController {
	@GetMapping("/list")
	public String list() {
		return "boardList"; 
	}
}
  1. boardList.jsp를 만든다

1, 2 결과

  • 화면에서 Board를 클릭하면 게시판으로 넘어간다
  • 로그인을 하지 않아도 넘어간다
    -> 로그인 상태를 확인하도록 메서드를 만들자
  1. loginCheck 메서드를 만든다
    세션을 얻어서 세션에 id가 있는지
private boolean loginCheck(HttpServletRequest request) {
	HttpSession session = request.getSession();
	return session.getAttribute("id")!=null;
}
  1. 로그인 체크 메서드를 활용해서, 로그인을 했으면 board를 볼 수 있도록 하고
    로그인을 안했으면 다시 로그인 화면으로 이동
public String list(HttpServletRequest request) {
	if(!loginCheck(request))
		return "redirect:/login/login?toURL="+request.getRequestURL();
	return "boardList";
}

3, 4 결과

  • 로그인을 하지 않으면 다시 로그인 화면으로 넘어간다
  • 요청(request) 세션 객체(getSession)에 id가 없어서 로그인을 해도 id가 있는지(로그인을 했는지) 모른다
    -> 로그인 하면 세션 객체를 얻어 와서 세션 객체에 id 저장하도록 만든다
    loginController에서 id, pwd가 일치하면 세션에 id 저장
  1. 로그인 하면 세션 객체를 얻어 와서 세션 객체에 id 저장하도록 만든다
if(!loginCheck(id, pwd)) {		
	String msg = URLEncoder.encode("id 또는 pwd가 일치하지 않습니다.", "utf-8");			
	return "redirect:/login/login?msg="+msg;
}
HttpSession session = request.getSession();		
session.setAttribute("id", id);
  1. 로그아웃 메서드 추가
@GetMapping("/logout")
public String logout(HttpSession session) {
	//세션 종료
	session.invalidate();
	//홈으로 이동
	return "redirect:/"; 
}
  1. 홈, 게시판에서 로그인이 되어 있을 때는 로그아웃 버튼,
    로그인이 안되어 있을 때는 로그인 버튼
    변수 자리 만들어주고 조건으로 연결된 링크와 이름을 준다
<c:set var="loginOutLink" value="${sessionScope.id==null ? '/login/login' : '/login/logout'}"/>
<c:set var="loginOut" value="${sessionScope.id==null ? 'Login' : 'Logout'}"/>
.
.
<li><a href="<c:url value='${loginOutLink}'/>">${loginOut}</a></li> 

8. 로그인 안되어 있을 때 게시판 누르면 로그인 창이 뜨고,
로그인 하면 다시 홈이 아니라 바로 게시판 창으로 갈 수 있도록

  1. BoardController
    from: /ch2/ (홈)
    to : /boardList/
  2. loginForm.jsp
    from: /ch2/
    to: /login/login/
	@GetMapping("/login")
	public String loginForm() {
		return "loginForm";
	}
  1. LoginController
    from: login/login/
    to: login/login/
if(!loginCheck(id, pwd)) {
	String msg = URLEncoder.encode("id 또는 pwd가 일치하지 않습니다.", "utf-8");	
	return "redirect:/login/login?msg="+msg;
}
HttpSession session = request.getSession();
session.setAttribute("id", id);
  • 1은 BoardController의 정보를 알고 있지만 3은 모른다. 해당 url로 갈 수 없다
    1의 정보를 3까지 전달해주어야 한다
  • to 정보는 request.getRequestURL()을 사용하면 알 수 있다
  • from 정보는 request.getHeader("referer")를 사용하면 알 수 있다
  1. PerformanceFilter에서 request가 ServletRequest형으로 되어있기 때문에 형변환을 해준다
HttpServletRequest req = (HttpServletRequest)request;
String referer = req.getHeader("referer"); //어디서 요청했는지
String method = req.getMethod(); // 요청한 메서드
System.out.print("["+referer+"] -> "+ method+ "["+req.getRequestURI()+"]");
  1. 1에서 2로 값을 전달: GET 방법 사용 - 노출되어도 괜찮은 정보이기 때문에
return "redirect:/login/login?toURL="+request.getRequestURL();
  1. 2에서 3으로: POST 방법 사용 - hidden input을 만들어서 GET 방식으로 넘어온 url을 입력하고 POST 방식으로 같이 보낸다
<input type="hidden" name="toURL" value="${param.toURL}">
  1. 3에서 값을 받아서 redirect:/../ 가능
    로그인 매개변수로 input으로 넘어온 해당 url을 받고, 로그인이 되어 있을 때 toURL로 redirect 하도록 한다
toURL = toURL==null || toURL.equals("") ? "/" : toURL;
return "redirect:"+toURL;

세션을 늦게 시작하기

  • 세션이 필요없는 경우 세션을 늦게 만든다
  • 세션은 서버에 부담이기 때문
  • ksp view에 session = "true" or session = "false"
<%@ page session="false" %>
  • 세션 있을 때 true/fasle 둘 다 세션 안 만듦
  • 세션 없을 때 true 세션 만듦, false 세션 안 만듦
  • false라고 해서 기존 세션에 영향을 주지 않음, '새로' 만들지 않는 것
profile
안녕하세요. Chat JooPT입니다.

0개의 댓글