도메인이란?
화면, UI, 기술 인프라 등등의 영역을 제외한 시스템이 구현해야 하는 핵심 비즈니스 업무 영역
웹은 도메인에 의존하지만, 도메인은 웹에 유지하지 않는다.
쿠키의 사용 배경
HTTP 는 Stateless Protocol
그러므로 현재 로그인에 성공 시 회원임을 검증할 수 있는 쿠키를 만들어 웹 브라우저에 전달해 주어야 한다.
모든 요청에 쿠키를 포함하여 로그인이 된 상태인지 확인하자!
쿠키의 종류
세션 쿠키 : 브라우저 종료시까지만 유지(만료 날짜 생략 시)
영속 쿠키 : 만료 날짜까지 쿠키 유지
쿠키로 로그인/로그아웃 구현
쿠키 만들기(로그인) 🍪
로그인에 성공할 시에 쿠키를 만들어 주면 되겠다!
@PostMapping("/login")
public String login(@Validated @ModelAttribute LoginForm form, BindingResult bindingResult, HttpServletResponse response) {
...
// 쿠키 넣어주기
// 세션 쿠키 (쿠키에 시간 정보를 주지 않았으므로 )
Cookie idCookie = new Cookie("memberId", String.valueOf(loginMember.getId()));
response.addCookie(idCookie);
return "redirect:/";
}
쿠키 만료(로그아웃) 🍪💥
@PostMapping("/logout")
public String logout(HttpServletResponse response) {
expireCookie(response, "memberId");
return "redirect:/";
}
문제점
하지만 위의 방식(쿠키만으로 로그인 구현) 은 보안 이슈가 있다
쿠키 값은 조작이 가능하기 때문에 의미가 있는 정보를 쿠키에 담게 되면 쿠키에 보관된 정보를 훔쳐갈 수 있다.
해결 방법
쿠키를 탈취해서 해당 정보로 계속 로그인해올 가능성이 있다.
1. 그러므로 쿠키에 중요한 정보를 넣지 말고, 임의의 값(토큰)을 넣어 주자!
2. 토큰의 유지시간을 짧게(30분) 유지한다
서버-세션의 개념 적용하기
세션 저장소에 UUID를 생성해 이를 키(세션 ID)로 잡고, 세션 저장소에 값을 저장한다
이 UUID를 쿠키에 담아 웹 브라우저에 보내준다.
브라우저는 쿠키 저장소에 쿠키를 저장하고, 쿠키 정보(세션ID)로 세션 저장소를 조회해서 보관된 정보를 사용한다.
세션 원리 적용해보기
UUID로 세션의 키 값이 되는 SessionID를 만들어 주고, 이를 Map에 넣어 준 후 SessionId로 회원을 반환받도록 하자
세션 생성
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);// 상수로 만들기 ctrl+alt+c
response.addCookie(mySessionCookie);
}
세션 조회
public Object getSession(HttpServletRequest request) {
Cookie cookie = findCookie(request, SESSION_COOKIE_NAME);
if (cookie == null) {
return null;
}
return sessionStore.get(cookie.getValue());
}
public Cookie findCookie(HttpServletRequest request, String cookieName) {
Cookie[] cookies = request.getCookies();
if (cookies == null) {
return null;
}
return Arrays.stream(cookies)
.filter(cookie -> cookie.getName().equals(cookieName))
.findAny()
.orElse(null);
}
세션 만료
public void expire(HttpServletRequest request) {
Cookie cookie = findCookie(request, SESSION_COOKIE_NAME);
if (cookie != null) {
sessionStore.remove(cookie.getValue());
}
}
HttpSession 이용하기
세션 생성
HttpServletRequest를 필요로 한다
public String homeLoginV3(HttpServletRequest request, Model model) {
// Guest도 접근이 가능해야 함
HttpSession session = request.getSession();
getSession(default = true)
true 일 경우, 세션을 신규 생성
false 일 경우 세션이 존재할 경우 해당 세션을 반환
세션 삭제
HttpSession session = request.getSession(false);
if (session != null) {
session.invalidate();
}
세션 조회
Controller상에서의 SessionAttribute 사용
@GetMapping("/")
public String homeLoginV3Spring(@SessionAttribute(name = SessionConst.LOGIN_MEMBER, required = false) Member member, Model model) {
// Guest도 접근이 가능해야 함
if (member == null) {
return "home";
}
// 세션이 유지되면 로그인으로 이동
model.addAttribute("member", member);
return "loginHome";
}
처음 로그인할 때 세션ID 값이 함께 출력되어 나올 때 이를 방지하는 방법
출력되는 이유는 브라우저가 쿠키를 지원하지 않을 수 있기 때문이다
application.properties 에 한 줄 추가
server.servlet.session.tracking-modes=cookie
세션 정보와 타임아웃
세션이 종료되는 경우 : session.invalidate() - 로그아웃시 사용
그러나 유저는 직접 로그아웃 하기보다 브라우저를 종료하게 된다.
세션이 종료되지 않은채로 유지되어 세션이 많아지면 메모리를 많이 사용하게 될 수 밖에 없다
👉그래서! 타임아웃🕑을 설정
최근 요청시간을 기준으로 30분 정도 유지
1. 글로벌 적용
server.servlet.session.timeout=120 // 분 단위
2. 특정 세션에 적용
session.setMaxInactiveInterval(1800);
'Spring' 카테고리의 다른 글
Spring - Exception (0) | 2022.10.09 |
---|---|
MVC2 - Filter, Interceptor (1) | 2022.10.05 |
MVC2 - Bean Validation (0) | 2022.09.27 |
MVC2 - Validation (0) | 2022.09.27 |
File->MultipartFile (0) | 2022.07.26 |