스프링

스프링 MVC 2편 쿠키, 세션

수연정 2024. 3. 11. 16:04

쿠키

@PostMapping("/login")
public String login(@Valid @ModelAttribute LoginForm form, BindingResult
bindingResult, HttpServletResponse response) {
 if (bindingResult.hasErrors()) {
 return "login/loginForm";
 }
 Member loginMember = loginService.login(form.getLoginId(), 
form.getPassword());
 log.info("login? {}", loginMember);
 if (loginMember == null) {
 bindingResult.reject("loginFail", "아이디 또는 비밀번호가 맞지 않습니다."); return "login/loginForm";
 }
 //로그인 성공 처리
 //쿠키에 시간 정보를 주지 않으면 세션 쿠키(브라우저 종료시 모두 종료)
 Cookie idCookie = new Cookie("memberId", 
String.valueOf(loginMember.getId()));
 response.addCookie(idCookie);
 return "redirect:/";
}

 

Cookie idCookie = new Cookie("memberId", String.valueOf(loginMember.getId()));
response.addCookie(idCookie);

쿠키 생성 로직

 

@PostMapping("/logout")
public String logout(HttpServletResponse response) {
 expireCookie(response, "memberId");
 return "redirect:/";
}
private void expireCookie(HttpServletResponse response, String cookieName) {
 Cookie cookie = new Cookie(cookieName, null);
 cookie.setMaxAge(0);
 response.addCookie(cookie);
}

쿠키를 EXPIRE 시켜서 로그아웃 기능을 구현 할 수 있다.

 

세션

세션 ID를 생성하는데, 추정 불가능해야 한다.
UUID는 추정이 불가능하다.
Cookie: mySessionId=zz0101xx-bab9-4b92-9b32-dadb280f4b61
생성된 세션 ID와 세션에 보관할 값( memberA )을 서버의 세션 저장소에 보관한다.

 

@Component
public class SessionManager {
 public static final String SESSION_COOKIE_NAME = "mySessionId";
 private Map<String, Object> sessionStore = new ConcurrentHashMap<>();
 /**
 * 세션 생성
 */
 public void createSession(Object value, HttpServletResponse response) {
 //세션 id를 생성하고, 값을 세션에 저장
 String sessionId = UUID.randomUUID().toString();
 sessionStore.put(sessionId, value);
 //쿠키 생성
 Cookie mySessionCookie = new Cookie(SESSION_COOKIE_NAME, sessionId); response.addCookie(mySessionCookie);
 }
 /**
 * 세션 조회
 */
 public Object getSession(HttpServletRequest request) {
 Cookie sessionCookie = findCookie(request, SESSION_COOKIE_NAME);
 if (sessionCookie == null) {
 return null;
 }
 return sessionStore.get(sessionCookie.getValue());
 }
 /**
 * 세션 만료
 */
 public void expire(HttpServletRequest request) {
 Cookie sessionCookie = findCookie(request, SESSION_COOKIE_NAME);
 if (sessionCookie != null) {
 sessionStore.remove(sessionCookie.getValue());
 }
 }
 private Cookie findCookie(HttpServletRequest request, String cookieName) {
 if (request.getCookies() == null) {
 return null;
 }
 return Arrays.stream(request.getCookies())
 .filter(cookie -> cookie.getName().equals(cookieName))
 .findAny()
 .orElse(null);
 }
}

 

서블릿 HTTP 세션

@PostMapping("/login")
public String loginV3(@Valid @ModelAttribute LoginForm form, BindingResult
bindingResult, HttpServletRequest request) {
 if (bindingResult.hasErrors()) {
 return "login/loginForm";
 } Member loginMember = loginService.login(form.getLoginId(), 
form.getPassword());
 log.info("login? {}", loginMember);
 if (loginMember == null) {
 bindingResult.reject("loginFail", "아이디 또는 비밀번호가 맞지 않습니다.");
 return "login/loginForm";
 }
 //로그인 성공 처리
 //세션이 있으면 있는 세션 반환, 없으면 신규 세션 생성
 HttpSession session = request.getSession();
 //세션에 로그인 회원 정보 보관
 session.setAttribute(SessionConst.LOGIN_MEMBER, loginMember);
 return "redirect:/";
}

 

세션의 create 옵션에 대해 알아보자.
request.getSession(true)
세션이 있으면 기존 세션을 반환한다.
세션이 없으면 새로운 세션을 생성해서 반환한다.


request.getSession(false)
세션이 있으면 기존 세션을 반환한다.
세션이 없으면 새로운 세션을 생성하지 않는다. null 을 반환한다.


request.getSession() : 신규 세션을 생성하는 request.getSession(true) 와 동일하다.

 

@SessionAttribute

@GetMapping("/")
public String homeLoginV3Spring(
 @SessionAttribute(name = SessionConst.LOGIN_MEMBER, required = false) 
Member loginMember,
 Model model) {
 //세션에 회원 데이터가 없으면 home
 if (loginMember == null) {
 return "home";
 }
 //세션이 유지되면 로그인으로 이동
 model.addAttribute("member", loginMember);
 return "loginHome";
}
@SessionAttribute(name = "loginMember", required = false) Member loginMember

이것을 사용하면 이미 로그인 된 사용자를 찾을 수 있다.

 

세션의 종료 시점


세션의 종료 시점을 어떻게 정하면 좋을까? 가장 단순하게 생각해보면, 세션 생성 시점으로부터 30분 정도로 잡으면 될
것 같다. 그런데 문제는 30분이 지나면 세션이 삭제되기 때문에, 열심히 사이트를 돌아다니다가 또 로그인을 해서 세션
을 생성해야 한다 그러니까 30분 마다 계속 로그인해야 하는 번거로움이 발생한다.
더 나은 대안은 세션 생성 시점이 아니라 사용자가 서버에 최근에 요청한 시간을 기준으로 30분 정도를 유지해주는 것
이다. 이렇게 하면 사용자가 서비스를 사용하고 있으면, 세션의 생존 시간이 30분으로 계속 늘어나게 된다. 따라서 30
분 마다 로그인해야 하는 번거로움이 사라진다. HttpSession 은 이 방식을 사용한다.