세션이란?
- 서버에 저장됨 (톰캣의 세션저장소)
- 서로 관련된 요청들을 하나로 묶은 것
- 쿠키를 이용
- 브라우저(브라우저에서 쿠키를 저장함)마다 개별 저장소(session객체)를 서버에 제공
- 수동종료: invalidate(예:로그아웃)
- 자동종료: 시간초과
- 일반적으로 한세션 -> 로그인부터 로그아웃까지
- 서버에 부담이 가기 때문에 타임아웃필수, 세션에는 최소한의 정보만
- 브라우저에서 쿠키설정을 차단으로 해놓으면 url에 세션을 담아보내도록 설계 (jsp에선 url태그를 쓰면 자동으로 됨)
- 새로운 곳에서 요청이 올때마다 객체를 만듬(1대1대응)
세션의 생성과정
- 서버에서 세션객체를 만들고 응답시 세션아이디를 브라우저에 넘겨준다.
- 이후 요청시 브라우저에서 쿠키와 함께 세션아이디를 넘겨준다.
- 세션아이디를 통해 서버는 클라이언트를 식별한다.
세션 객체
- 브라우저마다 세션아이디는 달라짐
- 서버에서 세션객체 다루기
HttpSession session = request.getSession();
session.setAttribute("id","asdf");
session="true" or session="false"
- 세션을 시작할까?라고 묻는 옵션
- 로그인전에는 세션이 필요없다. 그러므로 필요 없는 페이지에는 세션을 session="false"
- 도중에 false인 페이지를 만난다고 세션이 끊기는 것이 아니다. 단지 true를 만나면 그 때부터 세션을 시작하는 것이다.
- session="false"일 때, sessionScope와 pageContext.session 사용불가
- getSession(true)는 session이 없는 경우 session을 생성한다.
-> session이 없어도 생성하지 안도록 하려면 getSession(false)로 사용하면 된다.
jsp에서는 맨위에 아래 문장을 넣어주면됨, default는 true
<%@ page session="false"%>
세션과 관련된 메소드
세션의 종료
- 수동 종료 (초단위)
HttpSesion session = request.getSession();
session.invalidate(); //세션을 즉시 종료
session.setMaxInactiveInterval(30*60); //예약종료(30분후)
- 자동종료- web.xml (분단위), 요청과 요청사이의 시간간격, 설정강력권장(서버부담커지기때문에)
<session-config>
<session-timeout>30</session-timeout>
<session-config>
쿠키와 세션의 비교
- 서버가 여러대이면 세션을 모든 서버에 검색(또는 동기화)해야 하기에 다중화에 불리하다.
- 쿠키는 보안에 불리하기 때문에 일반적으로(상황에 따라) 암호화하여서 사용한다.
예제
로그인시 로그인 로그아웃 버튼 바뀌는 jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<c:set var="loginOutLink" value="${sessionScope.id==null ? '/login/login' : '/login/logout'}"/> 여기
<c:set var="loginOut" value="${sessionScope.id==null ? 'Login' : 'Logout'}"/> 여기
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>fastcampus</title>
<link rel="stylesheet" href="<c:url value='/css/menu.css'/>">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.8.2/css/all.min.css"/>
</head>
<body>
<div id="menu">
<ul>
<li id="logo">fastcampus</li>
<li><a href="<c:url value='/'/>">Home</a></li>
<li><a href="<c:url value='/board/list'/>">Board</a></li>
<li><a href="<c:url value='${loginOutLink}'/>">${loginOut}</a></li> 여기
<li><a href="<c:url value='/register/add'/>">Sign in</a></li>
<li><a href=""><i class="fas fa-search small"></i></a></li>
</ul>
</div>
<div style="text-align:center">
<h1>This is HOME</h1>
<h1>This is HOME</h1>
<h1>This is HOME</h1>
</div>
세션과 매핑 관리하는 로그인 컨트롤러
로그인이 필요하게 된 이유(어디에 접속하려 했는지) 또는 어디서 로그인 시도를 했는지에 따라 반환하는 주소를 다르게 구현하기
-> request.getHeader("refer") 이용하면 어디서 요청이 왔는지 알 수 있음
-> request.getRequestURI() 또는 request.getRequestURL() 이용하면 어디에 접속하려고 했는지 알 수 있음
하지만 내부적으로 계속 주소를 옮겨다니다 보면(redirect,forwarding등 필요에 따라 다른 주소를 계속 넘어갈 수 있다.) 이전주소와 요청주소가 계속 바뀌기에 전달을 계속 해야한다.
-> GET방식은 주소에, POST방식은 hidden폼(jsp에 id인풋태그처럼 만드는데 히든으로) 하나 만들어서 넘긴다. tip)테스트할때는 보이게 해놓고 마지막에 히든으로 하면됨
toURL(요청주소를)폼에 저장했다가 다시 로그인을 할때 toURL을 같이 넘겨서 해당 주소로 이동하게 하면됨.
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/login")
public class LoginController {
@GetMapping("/login")
public String loginForm() {
return "loginForm";
}
@GetMapping("/logout")
public String logout(HttpSession session) { //request에서 get할 필요없이 바로 이렇게 session 받아올 수 있
// 1.세션종료
session.invalidate();
// 2.홈으로 이동
return "redirect:/";
}
@PostMapping("/login")
public String login(String id, String pwd, boolean rememberId, HttpServletRequest request,HttpServletResponse response, String toURL) throws UnsupportedEncodingException {
System.out.println("id= "+id);
System.out.println("pwd= "+pwd);
System.out.println("rememberId= "+rememberId);
//id와pwd를 확인
if(!loginCheck(id,pwd)) {
// 일치하지 않으면 loginForm으로 이동
String msg = URLEncoder.encode("id 또는 pwd가 일치하지 않습니다.","utf-8");
return "redirect:/login/login?msg="+msg;
}
//세션객체 얻어오기
HttpSession session = request.getSession();
//세션에 id를 저장
session.setAttribute("id",id);
//아이디와 패스워드 일치하면 쿠키생성,응답에 저장,홈으로 이동
if(rememberId) {
//쿠키저장
Cookie cookie = new Cookie("id",id);
response.addCookie(cookie);
} else {
//쿠키삭제
Cookie cookie = new Cookie("id",id);
cookie.setMaxAge(0);
response.addCookie(cookie);
}
toURL=toURL==null|| toURL.equals("") ? "/" : toURL;
return "redirect:"+ toURL;
}
private boolean loginCheck(String id, String pwd) {
return "dsa".equals(id) && "123".equals(pwd);
}
}
로그인상태에서만 보드페이지 접근할 수 있도록 하는 컨트롤러
로그인필요시 로그인 후에 자동으로 보드페이지로 이동되게
@Controller
@RequestMapping("/board")
public class BoardController {
@GetMapping("/list")
public String list(HttpServletRequest request) {
if(!loginCheck(request))
return "redirect:/login/login?toURL="+request.getRequestURL(); // 로그인을 안했으면 로그인 화면으로 이동
//반환 주소에 요청주소를 넣어서 반환
return "boardlist"; // 로그인을 한 상태이면, 게시판 화면으로 이동
}
private boolean loginCheck(HttpServletRequest request) {
// 1. 세션을 얻어서
HttpSession session = request.getSession();
// 2. 세션에 id가 있는지 확인, 있으면 true를 반환
return session.getAttribute("id")!=null;
}
}
'I leaned > 스프링,스프링부트' 카테고리의 다른 글
DispatcherServlet (0) | 2023.05.26 |
---|---|
예외처리 (0) | 2023.05.25 |
쿠키(Cookie) (0) | 2023.05.24 |
redirect와 forward (0) | 2023.05.23 |
@RequestMapping (0) | 2023.05.23 |