![[Spring] Session 직접 구현하기, 쿠키와 세션](https://img1.daumcdn.net/thumb/R750x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdJivND%2FbtsmWnSz0pv%2FX0AhPSzi4koow9AXsYmT90%2Fimg.png)
직접 구현하지 않고 세션을 사용하는 방법이 있으나 세션이 어떻게 만들어지는지 이해를 하고 쓰는 것과 아닌 것은 큰 차이가 있을 거라 생각합니다. 편하게만 개발하려고 하면 발전이 없다고 생각합니다.
본 글은 쿠키와 세션에 대한 이해를 하고 있음을 가정하고 작성된 글입니다.
쿠키와 세션
쿠키에 중요한 정보를 담아 사용하게 된다면 누군가가 악용할 위험이 있다. 개발자 모드에 진입에서 네트워크 정보를 보면 쿠키에 대한 정보가 그대로 드러난다. 따라서 쿠키에는 세션하고 연결할 정보만 저장해야 한다.
쿠키에 담을 정보를 세션에 담으면 된다. 세션은 서버에서 관리되기 때문에 클라이언트 차원에서 노출에 대한 위험이 없다.
사진을 보면 쿠키의 mySessionId와 세션의 sessionId가 동일하다. 중요한 정보는 세션의 value에 저장되어 있고 sessionId만 쿠키에 저장한다.
구현1 - 글
MySession
세션의 key에 uuid, value에 로그인에 성공한 객체를 저장합니다.
@Component
public class MySession {
// 세션 저장할 Map
private Map<String, Object> sessionStored = new HashMap<>();
// 세션 생성
public String createSession(Object value, HttpServletResponse response) {
String uuid = UUID.randomUUID().toString();
sessionStored.put(uuid, value);
Cookie cookie = new Cookie("mySessionId", uuid);
response.addCookie(cookie);
return uuid;
}
// 세션 가져오기
public Object getSession(String uuid) {
return sessionStored.get(uuid);
}
}
Login
bindingResult는 무시해도 됩니다.
세션을 생성하고 반환 값으로 uuid를 받습니다. 여기서 uuid는 loginUser(로그인 한 사용자)를 세션에 저장할 때 사용된 key입니다. RedirectAttribute를 통해 리다이렉트를 할 때 파라미터 값으로 uuid를 넘깁니다.
@PostMapping("/login")
public String loginCheck(@Validated LoginUser loginUser, BindingResult bindingResult,
RedirectAttributes redirectAttributes, HttpServletResponse response) {
if(bindingResult.hasErrors()) {
bindingResult.reject("loginFailed", "로그인 실패");
return "/login";
}
String uuid = session.createSession(loginUser, response);
redirectAttributes.addAttribute("mySessionId", uuid);
return "redirect:/home";
}
Home
로그인 유무에 따라 다른 화면을 보여주는 코드입니다.
@RequestParam에서 mySessionId 쿼리 파라미터가 날아왔는지에 따라서 mySessionId의 값 또는 null 값이 uuid 변수에 저장됩니다. null일 때는 로그인하지 않은 화면, 그 반대는 로그인 한 화면을 보여줍니다.
우리는 위에서 mySessionId를 넘기면서 리다이렉트를 했기 때문에 mySessionId에 uuid 값이 저장되어 있습니다. 따라서 session.getSession()을 통해 uuid에 저장된 loginUser를 가져오게 되고 로그인한 사용자의 화면을 보여주게 됩니다.
@GetMapping("/home")
public String home(@RequestParam(value = "mySessionId", required = false) String uuid, Model model) {
if(uuid == null) {
return "/home";
}
LoginUser user = (LoginUser) session.getSession(uuid);
model.addAttribute("user", user);
return "/loginHome";
}
구현2 - 그림
1. 로그인하지 않았을 때 홈 화면
2. 로그인 화면
3. test 사용자에 대한 세션 생성
로그인을 하면 세션을 생성합니다. 세션의 key에는 uuid, value에는 로그인된 객체가 저장됩니다.
세션을 생성할 때 사용된 uuid를 반환받아 리다이렉트할 때 mySession 쿼리 파라미터에 uuid 값을 담아 홈화면을 전송합니다.
String uuid = session.createSession(loginUser, response);
redirectAttributes.addAttribute("mySessionId", uuid);
return "redirect:/home";
4. 로그인 후 홈 화면
url을 보면 test 사용자의 세션 아이디가 담겨서 넘어 옵니다. 쿼리 파라미터로 받은 uuid로 세션에 저장된 로그인된 객체를 받아옵니다. 이 객체를 모델에 담아서 View에 전달하면 다음과 같은 화면이 나옵니다.
if(uuid == null) {
return "/home";
}
LoginUser user = (LoginUser) session.getSession(uuid);
model.addAttribute("user", user);
return "/loginHome";
결론
위의 과정을 HttpSession으로 처리할 수 있습니다.