📌가. 세션 기반
세션 기반의 로그인 창에서는 서버가 세션 객체에 사용자 정보를 저장하고, 클라이언트는 쿠키를 통해 세션을 식별한다. 서버가 세션 상태를 관리하므로 보안에 좋으나, 메모리를 많이 사용한다.
쉽게 말한다면,🫡
-> 사용자가 로그인
-> 서버가 "이 사람 로그인했음" 이라고 장부에 기록
-> 사용자에게 들고다니라면서 세션 ID를 쥐어줌.
-> 후에 사용자가 기능을 요청하면 서버가 장부를 본 후 서비스를 제공
📌나. 쿠키 기반
쿠키 기반의 로그인 창에서는 사용자 정보를 직접 쿠키에 저장하고, 클라이언트가 직접 인증 정보를 계속 전송하는 방식을 사용한다. 이는 구현이 간단하나, 쿠키 탈취 시 보안에 위험이 있다는 단점이 있다.
쉽게 말한다면,🫡
-> 로그인하면 서버가 이름표(쿠키)를 만들어서 사용자에게 줌.
-> 이후에 서버에 요청할 때마다 이름표(쿠키)를 보여줌.
-> 서버는 이름표(쿠키)만을 보고 로그인했다고 판단.
-> 즉, 서버가 기억하는 게 아닌, 사용자가 직접 쿠키를 들고 다니며 증명하는 방식.
📌다. 무상태 (세션, 쿠키 둘 다 이용하지 않음)
세션과 쿠키를 둘 다 사용하지 않고 구현한 로그인 창에서는 매 요청마다 토큰이나 자격 정보를 같이 보내기 때문에 서버 확장에 유리하나 매 처리마자 인증 처리가 필요하다는 단점이 있다.
마찬가지로 쉽게 말한다면,🫡
-> 서버는 기억을 하지 않겠다고 선언. (강하게 표현하자면)
-> 대신 사용자는 로그인할 때 토큰이라는 보증서를 발급받음.
-> 이후 요청 시마다 사용자는 토큰이라는 보증서를 함께 제출함.
-> 서버는 토큰을 검사 후 유효하면 처리를 해줌.
-> 즉, 은행에서 거래할 때 신분증 지참을 하듯이 지니고 다니는 방식.
📌총 정리
세션 -> 서버가 기억함
쿠키 -> 사용자가 기억함
무상태 -> 사용자가 항상 증명함
나는 위 3가지 방식 중 첫 번째인, "세션"을 이용한 로그인 창을 구현해보았다.
💡 요구사항
1. 아이디: 202301506
2. 비밀번호: printhaha
3. 로그인 성공하면 👉 /board/list로 이동 + "로그인 성공" 팝업
4. 로그인 실패하면 👉 "아이디 / 비밀번호가 틀렸습니다" 팝업 + 로그인창으로 다시 이동
5. 로그인 안하면 게시판 접근 불가
[1] LoginController.java - 로그인 요청 처리
@Controller
@RequestMapping("/board")
public class LoginController {
@GetMapping("/login") // GET 요청이 /board/login 으로 들어오면
public String loginForm() {
return "login"; // 로그인 폼 화면을 보여줌
}
@PostMapping("/login") // 로그인 버튼 눌렀을 때
public String login(@RequestParam("username") String username, // 입력한 아이디
@RequestParam("password") String password, // 입력한 비밀번호
HttpServletRequest request,
RedirectAttributes redirectAttributes) {
// 아이디와 비밀번호가 맞는지 확인
if ("202301506".equals(username) && "printhaha".equals(password)) {
// 세션 가져오기 (없으면 새로 만듦)
HttpSession session = request.getSession();
// 세션에 사용자 정보 저장
session.setAttribute("userId", username);
// 로그인 성공 메시지 넘기기
redirectAttributes.addFlashAttribute("message", "로그인에 성공했습니다.");
// 게시글 리스트로 이동
return "redirect:/board/list";
} else {
// 로그인 실패 메시지 넘기기
redirectAttributes.addFlashAttribute("error", "유효하지 않은 아이디 / 비번입니다. 다시 입력하세요.");
// 다시 로그인 페이지로 이동
return "redirect:/board/login";
}
}
}
[2] LoginInterceptor.java - 로그인 여부 체크(세션 검사)
public class LoginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 세션이 있는지 확인 (없으면 null)
HttpSession session = request.getSession(false);
// 로그인 안했으면
if (session == null || session.getAttribute("userId") == null) {
// 로그인 페이지로 강제 이동
response.sendRedirect("/board/login");
return false;
}
return true; // 로그인 되어있으면 계속 진행
}
}
[3] login.html & [4] boardlist.html
// 로그인 실패 시 alert 창
<script th:if="${error}" th:inline="javascript">
alert([[${error}]]);
</script>
</body>
</html>
// 로그인 성공 시 alert
<div th:if="${message}">
<script th:inline="javascript">
alert([[${message}]]);
</script>
</div>
로그인 창 첫 화면
로그인 성공 시(팝업 메세지 창 후 리스트 창으로 이동)
로그인 실패 시(팝업 메세지 창 후 다시 로그인 화면으로 이동)
로그인창 구현 방식이 여러 종류가 있는 지는 몰랐네요.. 정리해 주셔서 감사합니다!