SPRING MVC - Cookie, Session

sungjin0757·2021년 7월 28일
1

Spring

목록 보기
9/23
post-thumbnail

Cookie 및 Session이 필요한 이유

  1. HTTP는 무상태(stateless) 프로토콜( protocol)
    수 만명의 회원 정보를 연결 상태를 유지 한다면 엄청난 과부화가 걸릴 것입니다. 그리하여 서버가 응답을 보낸 후 Client와 Server의 연결을 끊게 됩니다. 물론 무수히 많은 요청을 처리할 수 있기에 좋은 방법이지만 Client의 상태를 지속적으로 확인하는 데 어려움이 있으므로 쿠키와 세션을 통해 사용자의 상태 정보를 관리하게 됩니다.

  2. 로그인 상황을 생각해 봅시다.
    로그인에 성공하게 되었을 때 로그인 상태를 유지 시키지 못한다면 로그인을 했어도 안 한 상태와 마찬가지일 것입니다.
    예를 들어, 게임이던지 쇼핑몰이던지 로그인 상태를 유지시키지 못한다면 플레이를 할 때마다 키워놨던 게임 케릭터를 못 불러 온다던지 아니면 주문을 한 것이 있는데 주문내역을 못 본다든지 이러한 문제점이 발생할 것 입니다.
    그렇기 때문에 로그인 상태를 유지 시키기 위해 쿼리 파라미터를 계속 유지 시키며 보낼 수도 있지만 이는 무척 번거롭기 때문에 쿠키 및 세션을 사용하게 됩니다.

쿠키 사용 방법

  1. Client가 Server에 로그인 요청
  2. Server는 OK 응답과 함께 쿠키(회원과 관련된 값!!으로 만듬)를 만들어서 같이 응답
  3. 이후 웹브라우저는 쿠키 값이 유지 되기 때문에
  • 쿠키의 종류
    1. 영속 쿠키: 설정된 만료 날짜까지 유지
    2. 세션 쿠키: 웹 브라우저 종료 시 까지 유지
  • 쿠키의 문제점
    1. 쿠키값만을 사용하게 되면 쿠키 값은 request 헤더에 다 노출 되므로 사용자가 임의의 값을 설정해버려 다른 사용자의 정보를 갈취할 수 있습니다.
    2. 한번 갈취당한 쿠키는 그 도둑이 평생 사용해버릴 수 있습니다. 위험하겠죠??
    • 이러한 문제로 인하여 Session을 사용하게 됩니다

세션 사용 방법

  1. Client가 Server에 로그인 요청
  2. Server는 임의의 값을 만들어 임의의 값과 Login을 요청한 Client의 객체 정보를 Id,Value 형태로 세션 저장소에 저장
  3. Server는 세션 저장소에 Id로 저장한 임의의 값을 쿠키로서 Client에게 전달.
  4. 이후 요청이 오면 Server는 세션 값을 통해 세션 저장소에서 Client의 정보를 유지 시켜주는 형식
  • 쿠키의 문제점 해결
    1. 임의의 값을 사용하기 때문에 사용자의 정보를 갈취할 수 없습니다. 누가 누군지 모르게 되죠.
    2. 세션에 만료 시간을 주어 해커가 털어 가도 사용 못하게끔!
    3. 쿠키 값 변조 불가능. UUID를 사용했기 때문

Servlet에서 지원하는 세션 기능을 사용해 봅 시다.

JSESSIONID라는 값으로 세션 아이디가 만들어 집니다!

로그인 서비스와 같은 기본적인 로그인 처리 기술은 이미 개발되었다는 전제 하에 세션이 어떻게 사용되는지만 간략히 코드로 보여드리겠습니다!

loginController

@PostMapping("/login")
    public String login(@ModelAttribute LoginForm form,  HttpServletRequest request){
       
        Member loginMember = loginService.login(form.getLoginId(), form.getPassword());
        
        HttpSession session = request.getSession();
        session.setAttribute("loginMember",loginMember);

        return "redirect:/";
    }
  • request.getSession()
    • 파라미터로 true 나 false 지정 가능 request.getSession(true), request.getSession(false)
      1. true 지정 시
        • 세션이 있으면 기존 세션 반환 없으면 새로 생성 후 반환
      2. false 지정 시
        • 세션이 있을 때만 기존 세션 반환 없으면 null 반환
      • default값은 true로 지정되어있음
    • 여기서는 login을 처음 하는 유저도 있으므로 true로 설정 되어야 함.
  • session.setAttribute("loginMember",loginMember);
    세션에 값을 저장하는 것. 여기서는 로그인에 성공한 객체를 세션의 value로 지정. 세션 value의 값은 여러가지가 될 수 있음.
    "loginMember"라는 문자열은 HttpSession에 데이터 보관 및 조회할 때, 사용. 한 Application내에서는 같은 이름을 중복적으로 사용하기 때문에 어느 한 곳에 상수로 지정해 놓고 쓰는 것도 좋은 방법!

logoutController

@PostMapping("/logout")
    public String logout(HttpServletRequest request){
        HttpSession session = request.getSession(false);
        
        if(session!=null){
            session.invalidate();
        }

        return "redirect:/";
    }
  • session.invalidate();
    세션을 그냥 제거 해 버리는 것 - 세션 아이디와 값을 저장소에서 제거

Session 값 다른 컨트롤러에서 활용하기
서블릿만을 이용할 때는 session.getAttribute()라는 코드를 활용하여 세션에서 반환된 값을 판단하는 별도의 로직이 필요하였습니다.
이제는! 스프링에서 @SessionAttribute를 지원함으로서 더 쉽게 사용 가능합니다!!

    @GetMapping("/test")
    @ResponseBody
    public String test(
            @SessionAttribute(name=SessionConst.LOGIN_MEMBER,required = false)Member member, HttpServletRequest request){

        if(member==null){
            return "home";
        }
        
        return member.getName();
    }

@SessionAttribute는 현재 웹브라우저에 설정된 세션의 값을 member 객체에 반환 시켜줍니다.

추가로
세션을 제거하기 위해서는 로그아웃 버튼을 눌러야하지만 대부분 로그아웃 버튼을 누르지 않고 웹 브라우저를 종료합니다.
이렇게 되면 세션이 남아있을 수도 있으므로 따로 서버에서 세션을 만들 때 세션을 끊어주는 시간을 정해야 합니다.
session.setMaxInactiveInterval(1800); 처럼 사용하면 됩니다. 파라미터는 초 단위로 설정 됩니다.
이렇게 설정 해 놓으면 세션의 종료 시점은 사용자의 마지막 요청으로 부터 +1800초 이후에 세션이 종료되게 됩니다.
세션의 종료 시점이 세션이 생성된 시점이라면 매우 불편하겠죠?? 1800초마다 막 끊기고 이래버리면 ..

실행 결과

  • ID는 sungjin, 가입 이름은 Sungjin으로 회원 가입된 상태

로그인 화면

@SetAttribute활용

request-header에 JSESSIONID라는 값의 쿠키가 존재하는 지

실행 결과가 모두 위에서 설명드린바와 같이 일치하는 모습을 보여드리고 있습니다! : )

이상으로 포스팅을 마치겠습니다. 감사합니다 :)

이 글은 인프런 김영한님의 '스프링 MVC 2편 - 백엔드 웹 개발 핵심 기술'을 수강하고 작성합니다.
출처:https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-mvc-2/dashboard

profile
WEB STUDY & etc.. HELLO!

0개의 댓글