[Http] 쿠키와 세션을 이용한 로그인 처리

Updated:

로그인 처리흐름

쿠키와 세션을 이용하여 로그인 기능을 구현하는 과정과 전체적인 흐름에 대해 알아보자

배경지식

로그인 처리흐름을 알아보기에 앞서 쿠키와 세션에 대해 간단히 알아볼 필요가 있다

  • 우선, HTTP는 무상태 프로토콜이기 때문에 Client-Server간 요청과 응답을 마친 이후에는 연결이 종료된다
  • 때문에 로그인 등 항상 특정 정보를 필요로 하는 경우에는 모든 요청에 해당 정보를 항상 포함해야 하는 번거로움과 보안의 문제가 발생할 수 있다
  • 여기서 쿠키라는 개념을 도입한다

쿠키

login1

  1. Client가 로그인 등 특정 요청을 하면 Server는 Http Response Header의 Set-Cookie값에 특정 쿠키를 담아 응답한다
  2. Client 측의 브라우저에서 해당 쿠키값을 쿠키 저장소에 보관한다
  3. 이후 모든 요청에 대해 Client는 Http Request Header의 Cookie값에 쿠키 저장소의 쿠키를 넣어 요청한다

그럼 이제부터 Spring Server 측에서 수행하는 동작에 대해 알아보자

@Controller
public class CookieController {

    @GetMapping("/")
    public String home(HttpServletRequest request, Model model) {
        Cookie cookie = Arrays.stream(request.getCookies())
                .filter(c -> c.getName().equals("cookieId"))
                .findFirst()
                .orElse(null);
        model.addAttribute("cookie", cookie);
        return "home";
    }

    @GetMapping("/cookie")
    public String setCookie(HttpServletResponse response) {
        Cookie cookie = new Cookie("cookieId", "1");
        response.addCookie(cookie);
        return "redirect:/";
    }
}
  • Client가 /cookie로 요청을 보내면 Server는 Cookie 인스턴스를 만들어 응답값에 포함한다
    • 이때 Spring은 응답을 위해 HttpServletResponse를 사용한다
    • Server는 Http Response Header에 Set-Cookie: cookieId=1 형식으로 담아 응답한다
  • 이후 /로 리다이렉트되며 여기서는 HttpServletRequest를 이용하여 해당 쿠키값을 받는다
    • Client는 Http Request Header에 Cookie: cookieId=1 형식으로 담아 요청한다

-> 위의 경우처럼 쿠키에 아이디값 등 유의미하고 예측가능한 값을 넣으면 웹브라우저에서 해당값을 변경하여 다른 사용자로 위장하여 접근할 수 있다는 보안상의 문제점이 발생한다

-> 즉, Server 측에서 임의의 토큰을 생성하고 아이디값 등과 매핑한후 쿠키에는 해당 토큰값을 넘기는 방식이 필요하고 여기서 세션이라는 개념이 도입된다

세션

한명의 사용자가 하나의 디바이스만을 사용한다고 가정했을때 한명의 사용자당 하나의 세션을 사용한다. 또한, 하나의 세션당 jsessionId라는 식별자 한개가 대응된다

login2

  1. Client가 로그인 등 특정 요청을 하면 필요한 값을 세션에 특정 키값에 따라 저장한다
  2. Server는 위 세션을 구분하는 식별자인 jsessionId 값을 Http Request Header의 Set-Cookie값에 넣어 응답한다
  3. Client 측의 브라우저에서 해당 쿠키값을 쿠키 저장소에 보관한다
  4. 이후 모든 요청에 대해 Client는 Http Request Header의 Cookie값에 쿠키 저장소의 쿠키를 넣어 요청한다

마찬가지로 Spring Server 측에서 수행하는 과정에 대해 코드로 살펴보자

@Controller
public class CookieController {

    @GetMapping("/")
    public String homeV2(@SessionAttribute(name = "memberId", required = false) Long memberId, Model model) {
        model.addAttribute("data", memberId);
        return "home";
    }

    @GetMapping("/cookie-session")
    public String setCookieV2(HttpServletRequest request) {
        HttpSession session = request.getSession(true);
        session.setAttribute("memberId", 1L);

        return "redirect:/";
    }
}
  • Client가 /cookie-session으로 요청을 보내면 Server는 쿠키값을 반환한다는 점은 동일하다
    • 다만, 세션이라는 개념을 도입하여 세션에 key-value값으로 필요한 값을 저장하고 해당 세션의 식별자값을 쿠키값으로 전달한다는 차이점이 있다
      • 여기서는 세션에 memberId라는 키값으로 1이라는 값이 저장된다
    • 세션을 사용하는 경우에 Spring은 HttpServletRequest를 사용한다
    • Server는 Http Response Header에 Set-Cookie: jsessionId=~ 형식으로 담아 응답한다
  • 이후 /로 리다이렉트되며 여기서는 @SessionAttribute를 이용하여 세션의 value값을 바로 받는다
    • @SessionAttributename 속성은 키값을, required 속성은 항상 받을지의 여부를 결정한다
  • 참고로 위와 같이 코드 작성 시에 Server 측에서는 Cookie값을 urlSet-Cookie 모두로 응답한다
    • 오직 Http Response Header의 Set-Cookie값으로 반환받기 위해서는 application.propertiesserver.servlet.session.tracking-modes=cookie를 추가해주면 된다

Leave a comment