스프링/스프링 MVC 패턴

서블릿 Http 세션

chanhee01 2023. 2. 28. 23:48

쿠키를 이용해서 하는 것은 보안 문제가 있기 때문에 세션을 이용하는 것이 좋다. 세션이라는 것은 임의의 특이한 코드를 사용자에게 무작위로 줘서 고유의 값으로 서버와 연결할 수 있게 해주는 것이다.

 

서블릿에서 지원하는 세션 기능을 사용해서 구현할 수 있다.

 

@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";
    }

    // 로그인 성공 처리
    // 세션이 있으면 있는 세션 반환, 없으면 신규 세션을 생성
    HttpSession session = request.getSession();
    // 세션에 로그인 회원 정보 보관
    session.setAttribute(SessionConst.LOGIN_MEMBER, loginMember);

    return "redirect:/";
}

return 위의 두 줄이 지켜봐야 할 줄이다. HttpServletRequest를 가져와서 session에 request의 session을 넣고 setAttribute로 고유 세션 값을 넘겨준다.

 

@PostMapping("/logout")
public String logoutV3(HttpServletRequest request) {
    HttpSession session = request.getSession(false); // true면 세션을 생성해주기 때문에 false
    if (session != null) {
        session.invalidate();
    }
    return "redirect:/";
}

로그아웃 할 때도 비슷한데 request.getSession()의 파라미터에 false를 넣어주는 이유는 true면 세션을 생성하기 때문에 이 때에는 확인하고 삭제 할 예정이기 때문에 false를 넣어줘야한다. 위의 로그인 세션에서 안 넣어준 이유는 true가 default 값이기 때문이다.

 

 

 

@GetMapping("/")
    public String homeLoginV3(HttpServletRequest request, Model model) {

        HttpSession session = request.getSession(false);
        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";
    }

홈 컨트롤러는 위와 같이 getSession을 false로 불러와서 session이 존재하지 않거나 회원 데이터가 없으면 home으로 가고 정상적으로 접근했으면 로그인 홈으로 넘기면서 모델에 attribute로 넘겨준다.

 

 

 

@GetMapping("/")
    public String homeLoginV3Spring(@SessionAttribute(name = SessionConst.LOGIN_MEMBER,
            required = false) Member loginMember, Model model) {
        // 세션을 생성하지 않기 때문에 가져올때만 @SessionAttribute 사용

        // 세션에 회원 데이터가 없으면 home
        if (loginMember == null) {
            return "home";
        }

        // 세션이 유지되면 로그인으로 이동
        model.addAttribute("member", loginMember);
        return "loginHome";
    }

스플링에서 지원하는 @SessionAttribute를 사용하면 위의 코드를 더 간결하게 줄일 수 있다. 위의 복잡한 코드들이 다 생략되지만 세션을 생성하지 않기 때문에 세션을 가져올 때만 사용해야한다는 주의점이 있다.

 

 

 

 

세션 타임아웃

session.invalidate()가 호출되면 세션이 삭제된다. 하지만 사용자가 로그아웃을 안 누르고 웹 브라우저를 끈다면 세션이 삭제되지 않을 것이다. 그렇기 때문에 세션 타임아웃을 잘 걸어줘야한다.

 

application.properties에

server.servlet.session.timeout=1800

를 추가해주면 사용자의 마지막 요청으로부터 1800초(30분)동안 요청이 없으면 세션을 삭제한다.

사용자의 로그인이 아니라 마지막의 요청으로부터 시간이기 때문에 사용자의 이용이 끝나면 안전하게 세션을 삭제할 수 있다.