이야기에 앞서 패키지 설계에 대해 알았다.
도메인이 가장 중요하다
도메인이란 화면, UI, 기술 인프라 등의 영역을 제외한 시스템이 구현해야 하는 핵심 비즈니스 업무 영역을 말한다.
도메인 패키지 외에 web
이란 패키지를 추가했다. web
의 경우 다른 기술로 대체될 수 있다는 점을 인지해야한다. 따라서 도메인 패키지의 내용은 독립적으로 작성되어야 하고 웹이 도메인 코드를 의존하여 만들어지는 것이다. 반대로 말하면 domain
은 web
을 참조하면 안된다.
domain
item
member
login
web
기본적으로 HTTP 통신을 하기 때문에 웹은 비연결성 특징이 있다. 그런데 로그인을 한번하고 나면 어떻게 로그인 상태를 유지할까? 쿼리 파라미터를 이용한 URL을 계속 보내야할까? 제목에서 봤듯이 쿠키를 이용하면 될 것 같다.
서버에 로그인으로 인증에 성공하면 HTTP response에 쿠키를 담아 브라우저에 전송한다면 앞으로 브라우저는 request에 해당 쿠키를 계속 보내줄 것이다.
브라우저를 종료하면 보통 로그아웃 되는 웹을 만들기 때문에 세션 쿠키를 이용하자.
@PostMapping("/login")
public String login(@validated @ModelAttribute LoginForm form, BindingResult bindingresult, HttpServletResponse response) {
검증 처리~
로그인 서비스로 로그인 확인~
로그인 성공한다면?
Cookie newCookie = new Cookie("memberId", String.valueOf(member.getId()));
response.addCookie(newCookie);
리턴
}
우선 member는 입력받은 로그인 정보를 바탕으로 찾은 저장된 회원 인스턴스다. 맵의 key, value처럼 새로운 쿠키를 생성해주고 이를 HttpServletResponse
에 addCookie
로 담아준다. 이러면 웹 브라우저는 종료 전까지 해당 회원의 쿠키값, 여기서는 회원의 id
를 보내준다.
만약 request
에 담긴 쿠키값을 받고 싶다면 @CookieValue
를 이용하면 된다.
@GetMapping("/")
public String homeLogin(@CookieValue(name = "memberId", required = false) Long memberId,
Model model) {
if (memberId == null) {
return "home";
}
쿠키는 key가 아니라 name
이라고 한다. 그리고 뒤에 required
를 false
로 한 이유는 로그인하지 않은 고객들이 해당 URL로 접근할 수 있도록 설정한 것이다.
그럼 사용자가 로그아웃 버튼을 누른다면 가지고 있던 쿠키를 지워줄 필요가 있어 보인다. 지우는 방법은 같은 쿠키 이름을 지정해주는데 쿠키 종료 날짜를 0으로 만드는 것이다.
@PostMapping("/logout")
public String logout(HttpServletResponse response) {
expireCookie(response, "memberId");
return "redirect:/";
}
private void expireCookie(HttpServletResponse response, String cookieName) {
Cookie cookie = new Cookie(cookieName, null);
cookie.setMaxAge(0);
response.addCookie(cookie);
}
쿠키 종료 날짜는 쿠키의 메서드인 setMaxAge()
를 통해 지정할 수 있다.
쿠키를 사용해서 로그인Id를 전달해서 로그인을 유지할 수 있었다. 그런데 여기에는 심각한 보안 문제가 있다.
보안 문제
F12
) Application Cookie 변경이 가능하다.로그인을 유지하는 방법 중 쿠키에 대해 알아보았다. 쿠키 클래스를 이용해 새로운 쿠키를 만들어보고 서블릿이 제공하는 간단한 함수로 쿠키를 추가했다. 뭔가 굉장히 간단한만큼 보안에 있어 심각한 문제들이 보인다. 바로 위에 작성한 대안을 실현하기 위한 방법 중 세션을 다음 시간에 알아보려한다.