GitHub

https://github.com/Choidongjun0830

Spring

쿠키와 세션

gogi masidda 2024. 1. 8. 14:07

쿠키의 보안 문제

쿠키에 memberId를 넣어서 사용하면 보안상의 문제가 있을 수 있다. 해커가 memberId를 바꾸어 다른 유저의 정보를 빼가거나 조작할 수 있다. 이를 막기 위해서는 쿠키에는 유저의 중요한 정보가 담겨 있으면 안되고, 쿠키에 사용되는 id가 시간이 지나면 사용할 수 없도록 만료되어야 한다.

그래서 세션 저장소를 이용해 UUID라는 예측할 수없는 id를 저장하여 사용해야 한다. 이렇게 만든 id를 쿠키에 담아 사용하면, 쿠키에는 유저의 중요한 정보가 담기지 않고, 예측할 수도 없다.


세션

세션 관리가 제공해야 하는 기능

  • 세션 생성
    • sessionId 생성 (임의의 추정 불가능한 랜덤 값)
    • 세션 저장소에 sessionId와 보관할 값 저장
    • sessionId로 응답 쿠키를 생성해서 클라이언트에 전달
  • 세션 조회
    • 클라이언트가 요청한 sessionId 쿠키의 값으로 세션 저장소에 보관 값 조회
  • 세션 만료
    • 클라이언트가 요청한 sessionId 쿠키의 값으로 세션 저장소에 보관한 sessionId와 값 제공

 

HttpSession을 사용하면 이 기능을 구현할 수 있다.

   @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());

        if(loginMember == null) {
            bindingResult.reject("loginFail", "아이디 또는 비밀번호가 맞지 않습니다.");
            return "login/loginForm";
        }

        //로그인 성공 처리
        //세션이 있으면 있는 세션 반환, 신규 세션을 생성 <- request.getSession()의 기능
        HttpSession session = request.getSession();
        //세션에 로그인 회원 정보 보관
        session.setAttribute(SessionConst.LOGIN_MEMBER, loginMember);
        
        return "redirect:/";
    }
    
    @PostMapping("/logout")
    public String logoutV3(HttpServletRequest request) {
        HttpSession session = request.getSession(false);
        if(session != null) {
            session.invalidate();
        }
        return "redirect:/";
    }

request.getSession()의 create 옵션(파라미터)

  • request.getSession(true)
    • true가 디폴트 
    • 세션이 있으면 기존 세션 반환
    • 세션이 없으면 새로운 세션 생성해서 반환
  • request.getSession(false)
    • 세션이 있으면 기존 세션 반환
    • 세션이 없으면 새로운 세션을 생성하지 않고 null 반환
@GetMapping("/")
    public String homeLoginV3(HttpServletRequest request, Model model) {

        HttpSession session = request.getSession(false);//true로 하면 로그인하지 않은 사용자도 세션이 만들어지게 됨.
        if(session == null) {
            return "home";
        }

        Member loginMember = (Member)session.getAttribute(SessionConst.LOGIN_MEMBER);

        //세션에 회원 데이터가 없으면 home
        if(loginMember == null) {
            return "home";
        }
        //세션이 유지되면 로그인 홈으로 이동
        model.addAttribute("member", loginMember);
        return "loginHome";
    }

 


HttpSession 기능에 더해 Spring이 제공하는 SessionAttribute 사용

@GetMapping("/")
    public String homeLoginV3Spring(
            @SessionAttribute(name = SessionConst.LOGIN_MEMBER, required = false)Member loginMember, Model model) {
        //Session에서 값을 찾아서 loginMember에 넣어줌


        //세션에 회원 데이터가 없으면 home
        if(loginMember == null) {
            return "home";
        }
        //세션이 유지되면 로그인 홈으로 이동
        model.addAttribute("member", loginMember);
        return "loginHome";
    }

이미 로그인된 사용자를 찾을 때 사용한다. 세션을 찾고, 세션에 들어있는 데이터를 찾는 번거로운 과정을 스프링이 한번에 해준다.


세션 정보와 타임 아웃

사용자가 로그아웃을 직접 누르면 세션이 삭제되지만, 사용자가 로그아웃을 누르지 않고 웹 브라우저를 종료시키면 HTTP가 비연결성이라서 서버 입장에서는 해당 사용자가 웹 브라우저를 종료한 것인지 아닌지 인식할 수 없다. 그래서 서버에서 세션 데이터를 언제 삭제할지 판단하기 어렵다.

세션을 사용자가 최근에 요청한 시점을 기준으로 일정 시간동안 유지시켜주는 방법이 있다. 그 일정 시간을 설정하는 방법은 글로벌 설정이 있고, 특정 세션 단위로 설정하는 방법이 있다.

글로벌 설정은 application.properties에 'server.servlet.session.timeout=60'와 같이 설정해주는 것이다. 기본 값은 1800(30분)이다. 이것은 분 단위로 설정해야 한다.

특정 세션 단위 설정은

session.setMaxInactiveInterval(60);

이와 같이 설정하면 된다.

 

 

728x90

'Spring' 카테고리의 다른 글

스프링 인터셉터  (1) 2024.01.09
서블릿 필터  (0) 2024.01.09
검증2 - Bean Validation  (0) 2024.01.06
검증1-Validation  (2) 2024.01.04
메시지, 국제화  (0) 2024.01.01