HTTPSession - 1
SessionManager
와 같은 방식으로 스프링은 HttpSession
기능을 지원한다.
단 이 때 쿠키 이름은 표준 값에 의해 JSESSIONID
에 해당하고 값은 추정 불가능한 랜덤 값이다.
HTTPSession의 사용
package hello.login.web;
// 추상클래스 VS 인터페이스로 사용하라
public abstract class SessionConst {
public static final String LOGIN_MEMBER = "loginMember";
}
HttpSession
에 데이터를 보관하고 조회할 때 같은 이름이 중복되어 사용되므로 상수를 하나 정의함.
@PostMapping("/login")
public String loginFormV3(@Validated LoginForm loginForm,
BindingResult bindingResult,
HttpServletRequest request){
if(bindingResult.hasErrors()){
return "login/loginForm";
}
Member loginMember = loginService.login(loginForm.getLoginId(), loginForm.getPassword());
if(loginMember == null){
bindingResult.reject("loginFail", "아이디 또는 비밀번호가 맞지 않습니다.");
return "login/loginForm";
}
// 로그인 처리 TODO 쿠키를 만들어서 브라우저로 전송하면 브라우저에서 요청시마다 쿠키를 함께 전달함
// 스프링에서 제공하는 HTTP 세션 매니저 사용
HttpSession session = request.getSession(); // 세션이 있으면 있는 세션 반환 없으면 새로 만들어서 반환함
// 세션에 로그인 회원 정보를 보관한다.
session.setAttribute(SessionConst.LOGIN_MEMBER, loginMember);
// 기본적으로 다 메모리에 저장됨
// 세션 생성하려면 .getSession에 파라미터를 true(근데 디폴트라 생략가능)
// false라고 하면 새로운 세션을 반환하지 않고 null로 반환한다.
//sessionManager.createSession(loginMember, response);
return "redirect:/";
}
세션 생성과 조회
request.getSession(true)
의 사용을 통해 기존 세션을 가져오가 없으면 세션을 생성할 수 있다
parameter의 값이 false
인 경우 세션이 있으면 기존 세션을 반환하고 없는 경우 null
을 반환한다.
request.getSession()
은 request.getSession(true)
와 동일하다.
세션에 로그인 회원 정보 보관하는 방법
session.setAttribute(SessionConst.LOGIN_MEMBER, loginMember)
세션에 데이터를 보관하는 방법은 @ModelAttribute
와 비슷하다.
하나의 세션에는 여러 값을 보관할 수 있다.
로그아웃 처리
@PostMapping("/logout")
public String logoutV3(HttpServletRequest request){
HttpSession session = request.getSession(false);
session.invalidate();
return "redirect:/";
}
session.invalidate()
를 통해 세션을 제거할 수 있다.
@GetMapping("/")
public String homeLoginV3(HttpServletRequest request, Model model){
// 쿠키 값은 String인데 스프링이 알아서 Converting 해줌
HttpSession session = request.getSession(false);
if(session == null){
return "home";
}
Member loginMember = (Member) session.getAttribute(SessionConst.LOGIN_MEMBER);
if(loginMember == null){
return "home";
}
model.addAttribute("member", loginMember);
return "loginHome";
}
request.getSession(false)
: true
를 사용하면 의미없는 세션이 만들어진다.session.getAttribute(SessionConst.LOGIN_MEMBER)
: 로그인 시점에 세션에 보관한 회원 객체를 찾는다.
HTTPSession - 2
@SessionAttribute
스프링은 세션을 더 편리하게 관리할 수 있도록 위와 같은 애노테이션을 제공한다.
이미 로그인 된 사용자를 찾을 때 사용하면 되나, 직접 세션을 생성하지는 않는다
@GetMapping("/")
public String homeLoginV3Spring(@SessionAttribute(name = SessionConst.LOGIN_MEMBER, required = false)
Member loginMember,
Model model){
// 쿠키 값은 String인데 스프링이 알아서 Converting 해줌
// HttpSession session = request.getSession(false);
//
// if(session == null){
// return "home";
// }
//
// Member loginMember = (Member) session.getAttribute(SessionConst.LOGIN_MEMBER);
if(loginMember == null){
return "home";
}
model.addAttribute("member", loginMember);
return "loginHome";
}
}
세션 정보와 타임아웃 설정
세션이 제공하는 정보는 다음 코드를 통해 얻을 수 있다
package hello.login.web.session;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.Date;
@Slf4j
@RestController
public class SessionInfoController {
@GetMapping("/session-info")
public String sessionInfo(HttpServletRequest request){
HttpSession session = request.getSession(false);
if(session == null){
return "세션이 없습니다";
}
session.getAttributeNames().asIterator()
.forEachRemaining(name-> log.info("session name = {}, value = {} ", name, session.getAttribute(name)));
log.info("sessionId = {}", session.getId());
log.info("getMaxInactiveInterval={}", session.getMaxInactiveInterval());
log.info("creationTime={}", new Date(session.getCreationTime()));
log.info("lastAccessedTime={}", new Date(session.getLastAccessedTime()));
log.info("isNew={}", session.isNew());
return "세션 출력";
}
}
sessionId
: 세션 ID / JSESSIONID
의 값에 해당한다maxInactiveInterval
: 세션의 유효시간 : 단위(초)creationTime
: 세션 생성 일시lastAccessedTime
: 세션과 연결된 사용자가 최근에 서버에 접근한 시간
클라이언트에서 서버로 sessionId
(JSESSIONID
)를 요청한 경우에 갱신
세션 타임아웃 설정
session.invalidate()
는 /logout
을 통한 컨트롤러 호출시 실행된다.
그런데 유저 대부분은 로그아웃 버튼을 누르지 않는다. 브라우저를 그냥 꺼버리지
그러면 서버 상에서는 이 쿠키에 대한 정보가 남아있게 되는데 비연결성을 가진 HTTP 규약은
서버에서 세션 데이터를 언제 삭제할 것인지 판단하기 어려운 난제를 남긴다.
남아있는 세션을 오래 보관하면 JSESSIONID
가 탈취되었을 경우 오랜시간이 지나도 악의적인 요청을 계속할 수 있다. 이 세션들도 메모리에 생성되는데 10만명의 로그인이 실행되면 세션 10만개가 서버에 생성된다.
세션이 메모리를 차지하는 범주가 감당 가능한 수준을 넘어서면 서버가 죽는다.
따라서 세션의 종료 시점을 잘 간을 재서 설정해줘야하는데
열심히 사용하고 있는 사이트가 30분 마다 로그인된다고 생각해보자, 사실 은행 사이트나 보안이 주요한 사이트들은 timeout
을 고정으로 잡아서 갱신하지 않는 이상 자동 로그아웃 처리하는데 편의성이 보안성보다 우선시되는 대부분의 사이트들에서는 다른 전략이 필요하다
그래서 세선 생성 시점이 아닌 최근에 요청한 시간을 기준으로 30분 정도를 유지하는 전략을 사용한다.HttpSession
은 이 전략을 사용한다.
스프링 부트 설정을 다음과 같이 진행함으로써 글로벌하게 세션 타임아웃 시간을 설정할 수 있다.session.setMaxInactiveInterval(1800)
세션에는 최소한의 데이터만 보관하는게 좋다, 안그러면 메모리가 감당이 안될 것이다.
디폴트를 30분이라 생각하자.
'스프링 공부 (인프런 김영한 선생님) > 스프링 MVC 2편' 카테고리의 다른 글
[스프링 웹 MVC 2편] 011. 로그인 처리 - 인터셉터 (0) | 2023.08.18 |
---|---|
[스프링 웹 MVC 2편] 010. 로그인 처리 - 필터 (0) | 2023.08.18 |
[스프링 웹 MVC 2편] 008. 로그인 처리 - 쿠키. 세션 (0) | 2023.08.16 |
[스프링 웹 MVC 2편] 007. Bean Validation (0) | 2023.08.15 |
[스프링 웹 MVC 2편] 006. Validation (2) (0) | 2023.08.15 |
HTTPSession - 1
SessionManager
와 같은 방식으로 스프링은 HttpSession
기능을 지원한다.
단 이 때 쿠키 이름은 표준 값에 의해 JSESSIONID
에 해당하고 값은 추정 불가능한 랜덤 값이다.
HTTPSession의 사용
package hello.login.web;
// 추상클래스 VS 인터페이스로 사용하라
public abstract class SessionConst {
public static final String LOGIN_MEMBER = "loginMember";
}
HttpSession
에 데이터를 보관하고 조회할 때 같은 이름이 중복되어 사용되므로 상수를 하나 정의함.
@PostMapping("/login")
public String loginFormV3(@Validated LoginForm loginForm,
BindingResult bindingResult,
HttpServletRequest request){
if(bindingResult.hasErrors()){
return "login/loginForm";
}
Member loginMember = loginService.login(loginForm.getLoginId(), loginForm.getPassword());
if(loginMember == null){
bindingResult.reject("loginFail", "아이디 또는 비밀번호가 맞지 않습니다.");
return "login/loginForm";
}
// 로그인 처리 TODO 쿠키를 만들어서 브라우저로 전송하면 브라우저에서 요청시마다 쿠키를 함께 전달함
// 스프링에서 제공하는 HTTP 세션 매니저 사용
HttpSession session = request.getSession(); // 세션이 있으면 있는 세션 반환 없으면 새로 만들어서 반환함
// 세션에 로그인 회원 정보를 보관한다.
session.setAttribute(SessionConst.LOGIN_MEMBER, loginMember);
// 기본적으로 다 메모리에 저장됨
// 세션 생성하려면 .getSession에 파라미터를 true(근데 디폴트라 생략가능)
// false라고 하면 새로운 세션을 반환하지 않고 null로 반환한다.
//sessionManager.createSession(loginMember, response);
return "redirect:/";
}
세션 생성과 조회
request.getSession(true)
의 사용을 통해 기존 세션을 가져오가 없으면 세션을 생성할 수 있다
parameter의 값이 false
인 경우 세션이 있으면 기존 세션을 반환하고 없는 경우 null
을 반환한다.
request.getSession()
은 request.getSession(true)
와 동일하다.
세션에 로그인 회원 정보 보관하는 방법
session.setAttribute(SessionConst.LOGIN_MEMBER, loginMember)
세션에 데이터를 보관하는 방법은 @ModelAttribute
와 비슷하다.
하나의 세션에는 여러 값을 보관할 수 있다.
로그아웃 처리
@PostMapping("/logout")
public String logoutV3(HttpServletRequest request){
HttpSession session = request.getSession(false);
session.invalidate();
return "redirect:/";
}
session.invalidate()
를 통해 세션을 제거할 수 있다.
@GetMapping("/")
public String homeLoginV3(HttpServletRequest request, Model model){
// 쿠키 값은 String인데 스프링이 알아서 Converting 해줌
HttpSession session = request.getSession(false);
if(session == null){
return "home";
}
Member loginMember = (Member) session.getAttribute(SessionConst.LOGIN_MEMBER);
if(loginMember == null){
return "home";
}
model.addAttribute("member", loginMember);
return "loginHome";
}
request.getSession(false)
: true
를 사용하면 의미없는 세션이 만들어진다.session.getAttribute(SessionConst.LOGIN_MEMBER)
: 로그인 시점에 세션에 보관한 회원 객체를 찾는다.
HTTPSession - 2
@SessionAttribute
스프링은 세션을 더 편리하게 관리할 수 있도록 위와 같은 애노테이션을 제공한다.
이미 로그인 된 사용자를 찾을 때 사용하면 되나, 직접 세션을 생성하지는 않는다
@GetMapping("/")
public String homeLoginV3Spring(@SessionAttribute(name = SessionConst.LOGIN_MEMBER, required = false)
Member loginMember,
Model model){
// 쿠키 값은 String인데 스프링이 알아서 Converting 해줌
// HttpSession session = request.getSession(false);
//
// if(session == null){
// return "home";
// }
//
// Member loginMember = (Member) session.getAttribute(SessionConst.LOGIN_MEMBER);
if(loginMember == null){
return "home";
}
model.addAttribute("member", loginMember);
return "loginHome";
}
}
세션 정보와 타임아웃 설정
세션이 제공하는 정보는 다음 코드를 통해 얻을 수 있다
package hello.login.web.session;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.Date;
@Slf4j
@RestController
public class SessionInfoController {
@GetMapping("/session-info")
public String sessionInfo(HttpServletRequest request){
HttpSession session = request.getSession(false);
if(session == null){
return "세션이 없습니다";
}
session.getAttributeNames().asIterator()
.forEachRemaining(name-> log.info("session name = {}, value = {} ", name, session.getAttribute(name)));
log.info("sessionId = {}", session.getId());
log.info("getMaxInactiveInterval={}", session.getMaxInactiveInterval());
log.info("creationTime={}", new Date(session.getCreationTime()));
log.info("lastAccessedTime={}", new Date(session.getLastAccessedTime()));
log.info("isNew={}", session.isNew());
return "세션 출력";
}
}
sessionId
: 세션 ID / JSESSIONID
의 값에 해당한다maxInactiveInterval
: 세션의 유효시간 : 단위(초)creationTime
: 세션 생성 일시lastAccessedTime
: 세션과 연결된 사용자가 최근에 서버에 접근한 시간
클라이언트에서 서버로 sessionId
(JSESSIONID
)를 요청한 경우에 갱신
세션 타임아웃 설정
session.invalidate()
는 /logout
을 통한 컨트롤러 호출시 실행된다.
그런데 유저 대부분은 로그아웃 버튼을 누르지 않는다. 브라우저를 그냥 꺼버리지
그러면 서버 상에서는 이 쿠키에 대한 정보가 남아있게 되는데 비연결성을 가진 HTTP 규약은
서버에서 세션 데이터를 언제 삭제할 것인지 판단하기 어려운 난제를 남긴다.
남아있는 세션을 오래 보관하면 JSESSIONID
가 탈취되었을 경우 오랜시간이 지나도 악의적인 요청을 계속할 수 있다. 이 세션들도 메모리에 생성되는데 10만명의 로그인이 실행되면 세션 10만개가 서버에 생성된다.
세션이 메모리를 차지하는 범주가 감당 가능한 수준을 넘어서면 서버가 죽는다.
따라서 세션의 종료 시점을 잘 간을 재서 설정해줘야하는데
열심히 사용하고 있는 사이트가 30분 마다 로그인된다고 생각해보자, 사실 은행 사이트나 보안이 주요한 사이트들은 timeout
을 고정으로 잡아서 갱신하지 않는 이상 자동 로그아웃 처리하는데 편의성이 보안성보다 우선시되는 대부분의 사이트들에서는 다른 전략이 필요하다
그래서 세선 생성 시점이 아닌 최근에 요청한 시간을 기준으로 30분 정도를 유지하는 전략을 사용한다.HttpSession
은 이 전략을 사용한다.
스프링 부트 설정을 다음과 같이 진행함으로써 글로벌하게 세션 타임아웃 시간을 설정할 수 있다.session.setMaxInactiveInterval(1800)
세션에는 최소한의 데이터만 보관하는게 좋다, 안그러면 메모리가 감당이 안될 것이다.
디폴트를 30분이라 생각하자.
'스프링 공부 (인프런 김영한 선생님) > 스프링 MVC 2편' 카테고리의 다른 글
[스프링 웹 MVC 2편] 011. 로그인 처리 - 인터셉터 (0) | 2023.08.18 |
---|---|
[스프링 웹 MVC 2편] 010. 로그인 처리 - 필터 (0) | 2023.08.18 |
[스프링 웹 MVC 2편] 008. 로그인 처리 - 쿠키. 세션 (0) | 2023.08.16 |
[스프링 웹 MVC 2편] 007. Bean Validation (0) | 2023.08.15 |
[스프링 웹 MVC 2편] 006. Validation (2) (0) | 2023.08.15 |