<< 학습 목표 >>
1. 세션을 활용해 로그인 상태를 기억할 수 있다.
3. 세션에 저장된 상태 정보를 여러 서블릿에서 활용할 수 있다.
3. 서블릿으로 동적인 웹 페이지를 전달할 수 있다.
프로젝트(서비스)가 상태 정보를 저장해야되는 상황, 저장된 상태 정보를 사용해야되는 상황은 빈번히 발생함
먼저 네이버를 보자
네이버는 사용자의 로그인 상태를 기억하고 사용자가 로그인 전 이라면 로그인 전 화면을 보여주고 로그인 후 라면 로그인 후 화면을 보여주고 있음
우리가 만든 사이트에서도 로그인 상태를 기억하고 이를 활용해보자
로그인 서블릿에서 로그인에 성공했을 경우 세션에 로그인에 성공했다는 상태를 저장하자
지난 Chapter에서 만든 프로젝트의 서블릿은 member 패키지 안에 있음
member 패키지 내 MemberLogin 서블릿에서 로그인에 성공했을 때에 아래와 같이 추가하자
( 코드가 길어 바꿔야되는 부분만 캡쳐 )
로그인에 성공했다면 세션에 isLogin에 true를 저장했음(1)
이렇게 사용자가 로그인에 성공했다는 상태 정보를 저장할 수 있음
이제 로그인이 필요한 많은 곳에서 로그인 상태 정보를 활용할 수 있음
사용자가 회원 가입 페이지로 접속한다는건 회원 가입을 하지 않았다는 것
그렇다는건 당연히 로그인도 하지 않았다는 것
그러므로 회원 가입 페이지로 이동할 수 있는 회원은 로그인을 하지 않은 회원 뿐!
그러나 우리 서비스에서는 로그인을 했어도 회원 가입 페이지로 이동할 수 있음
회원 가입 페이지로 이동시켜주는 서블릿(member 패키지 -> MemberJoin서블릿)에서 세션을 활용해
1. 세션을 활용해 로그인 여부를 확인함
2. 로그인한 사용자는 메인 페이지로 리다이렉트 시키고
3. 로그인을 하지 않은 사용자만 회원 가입 페이지로 포워딩 시킴
만약 왜? 로그인을 한 상태라면 리다이렉트를 시키고 왜? 로그인을 하지 않은 상태라면 포워딩을 시키는 거지? 라는 생각이 들면 리다이렉트, 포워딩과 관련된 내용들을 더 복습해야함
로그인 페이지도 회원 가입 페이지와 마찬가지임
로그인 페이지로 접속하는 사용자는 로그인을 하지 않은 사용자임
로그인을 한 사용자가 다시 로그인 페이지로 접속하지 않을 것
로그인 페이지로 이동시켜주는 서블릿(member 패키지 -> MemberLogin서블릿)에서 세션을 활용해
1. 세션을 활용해 로그인 여부를 확인함
2. 로그인한 사용자는 메인 페이지로 리다이렉트 시키고
3. 로그인을 하지 않은 사용자만 로그인 페이지로 포워딩 시킴
이번에는 세션을 활용해서 아예 메인 페이지를 개선하자
로그인을 하지 않은 사용자는 메인 페이지에 회원가입, 로그인 버튼만 보이도록...
로그인을 한 사용자는 메인 페이지에 회원 정보 수정, 회원 탈퇴 버튼만 보이도록...
이제 동적인 메인 페이지를 만들어야함
앞 글에서 쿠키를 사용한 웹 페이지를 만들기 위해 JS 라이브러리를 추가하고 JS를 사용해 동적인 로그인 페이지를 만들었음
이번에도 JS를 사용해 동적인 메인 페이지를 만들 수 있을까?
그렇지 않음
쿠키는 클라이언트에 저장되므로 클라이언트 사이드 언어인 JS로 핸들링 할 수 있음
세션은 서버에 저장되므로 서버 사이드 언어인 Servlet, JSP만 핸들링 할 수 있음
JSP는 배우지 않았으니 Servlet으로 동적인 메인 페이지를 만들어보자
( 이 부분을 보면 앞 글에서 쿠키를 사용한 동적인 로그인 페이지를 패쓰한 이유를 알 수 있음 )
메인 페이지로 포워딩 시켜주는 서블릿에서 이제 포워딩을 시켜주면 안되고 동적인 웹 페이지를 전달해줘야함
과정을 먼저 설명하면
1. 세션을 활용해 로그인 여부를 확인함
2-1. 메인 페이지를 출력함
2-2. 메인 페이지의 메뉴 버튼을 출력할 때 로그인을 한 사용자 라면
2-3. 회원 정보 수정, 회원 탈퇴 버튼을 출력함
2-4. 메인 페이지의 메뉴 버튼을 출력할 때 로그인을 하지 않은 사용자 라면
2-5. 회원 가입, 로그인 버튼을 출력함
코드가 기므로 더보기를 참고해 메인 서블릿(member 패키지 -> MemberMain 서블릿)에 아래 코드를 추가하자
이제 메인 페이지 (WEB-INF 폴더 -> member -> index.html) 이 필요 없음
왜? MemberMain 서블릿에서 메인 페이지를 직접 출력하고 있으므로
package member;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
@WebServlet("/member")
public class MemberMain extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HttpSession session = request.getSession();
boolean isLogin = session.getAttribute("isLogin") != null;
response.setCharacterEncoding("UTF-8");
PrintWriter pw = response.getWriter();
pw.print("<!DOCTYPE html>");
pw.print("<html>");
pw.print("<head>");
pw.print(" <meta charset=\"UTF-8\">");
pw.print(" <title>연습 프로젝트</title>");
pw.print(" <link rel=\"stylesheet\" type=\"text/css\" href=\"/css/public/common.css\">");
pw.print(" <link rel=\"stylesheet\" type=\"text/css\" href=\"/css/index.css\">");
pw.print("</head>");
pw.print("<body>");
pw.print(" <header><< 메인 >></header>");
pw.print(" <main>");
pw.print(" <ul>");
if(isLogin) {
pw.print(" <li><a href=\"/member/update\">회원 정보 수정</a></li>");
pw.print(" <li><a href=\"#\">회원 탈퇴</a></li>");
} else {
pw.print(" <li><a href=\"/member/join\">회원가입</a></li>");
pw.print(" <li><a href=\"/member/login\">로그인</a></li>");
}
pw.print(" </ul>");
pw.print(" </main>");
pw.print("</body>");
pw.print("</html>");
}
}
이제 서버를 시작한 후 메인 페이지로 들어가보자
로그인 하기 전이라면 회원 가입, 로그인 버튼만 보이고 로그인 한 후라면 회원 정보 수정, 회원 탈퇴 버튼이 보일 것
또 일부로 회원 가입 페이지의 URL(http://localhost/member/join)을 입력해보고 로그인 페이지의 URL(http://localhost/member/login)을 입력해보자
이렇게 로그인 상태 정보를 사용해 더 실제와 같은 서비스로 발전시킬 수 있음
마지막으로 두 가지만 더 적용해보자
첫번째, 회원 가입 완료 페이지는 회원 가입을 한 후 보는 화면임
그러나 지금 우리는 회원 가입 완료 페이지 URL을 입력하면 접속할 수 있음
1. 회원 가입 서블릿에서 회원 가입을 완료 했을 경우 세션에 회원 가입 완료 상태를 저장
<< 회원 가입 서블릿 ( member 패키지 -> MemberJoin 서블릿 )
회원 가입에 성공했다면 세션에 회원 가입 완료 상태 저장
코드가 길어 일부만 캡쳐함

2. 회원 가입 완료 페이지로 포워딩 하기 전 회원 가입 완료 상태인 사용자인지 확인
package member;
import java.io.IOException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
@WebServlet("/member/joinSuccess")
public class MemberJoinSuccess extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HttpSession session = request.getSession();
boolean successJoin = session.getAttribute("successJoin") != null;
if(successJoin) {
RequestDispatcher rd = request.getRequestDispatcher("/WEB-INF/member/joinSuccess.html");
rd.forward(request, response);
} else {
response.sendRedirect("/member");
}
}
}
두 번째, 페이지 마다 로그인 상태 정보를 활용하므로 [ 로그아웃 ] 메뉴도 필요함
로그아웃은 로그인을 한 사용자에게 보여지는 메뉴임
1. 메인 페이지에 로그아웃 버튼 추가
메인 페이지를 출력하는 메인 서블릿(member 패키지 -> MemberMain 서블릿)에 로그인을 한 회원에게 보여줄 메뉴 부분에 다음과 같이 추가(1)
2. 로그아웃 기능 추가
Member 패키지 -> MemberLogout 서블릿 추가 후 아래 코드를 추가하자
package member;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
@WebServlet("/member/logout")
public class MemberLogout extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HttpSession session = request.getSession();
session.invalidate();
response.sendRedirect("/member");
}
}
로그아웃 기능에서는 세션을 삭제(1) 하고 메인 페이지로 리다이렉트 하고 있음
세션에 여러 정보가 많이 들어있다면 로그인 여부를 확인하는 데이터만 삭제해야하지만 우리 세션에는 로그인 여부를 확인하는데 필요한 데이터만 들어있으므로 세션을 삭제했음
지난 글( https://codingaja.tistory.com/59 ) 에서 요즘에는 [ 아이디 기억하기 ] 대신 [ 로그인 상태 유지 ] 를 구현하는 추세라고 했음
로그인 상태 유지는 한번 로그인을 하고 난 이후에 로그아웃을 하기 전까지는 평생 쭉 로그인 상태로 유지되는 것으로 내일 또는 일주일 뒤 또는 일년 뒤에 다시 이 서비스에 접속하더라도 번거롭게 로그인 할 필요가 없는 것을 말함
서블릿으로 [ 로그인 상태 유지 ] 를 구현하기에는 한계가 있음
인터넷에 [ 로그인 상태 유지 ] 또는 [ 자동 로그인 ] 키워드로 검색하면 세션 아이디를 쿠키에 저장해 사용자가 다음번에 우리 서비스에 접속했을 때 쿠키에 저장된 세션 아이디를 가져와 로그인 상태를 유지하는것으로 구현되어있음
그러나 이는 좋은 생각은 아닌 듯 함
쿠키의 단점은 사용자 컴퓨터에 저장됨
따라서 쿠키에는 중요한 개인 정보는 저장하면 안됨
특정 사용자의 로그인 상태 정보를 취득할 수 있는 세션 아이디를 쿠키에 저장해두면 해커가 손쉽게 사용자의 로그인 상태 정보를 취득할 수 있음
제가 생각했을 때는 사용자가 우리 서비스에 접속했을 때 사용자가 보내는 어떤 고유한 키값을 활용해 세션 아이디를 암호화 하는 과정이 필요해보임
보안, 암호화 관련된 기초 지식이 많이 필요한 기능 같은데 다른 블로그들은 너무 쉽게 생각하는거 아닐까...
내가 너무 과하게 생각하고 있나 싶어 chatGPT에게 물어보니 위와 같은 방식은 보안에 큰 문제가 있다고 함
서블릿으로는 불가능 하지만 스프링 시큐리티에 RememberMe 기능을 사용하면 보안을 강화할 수 있다고 함
chatGPT가 항상 정답은 아니지만 내 생각과 같으므로 정답을 알려줬다고 생각함
따라서 Servlet 을 사용해서는 보안이 강화된 자동 로그인은 구현할 수 없을 듯 함
'Servlet + JSP > Serlvet-Chapter05' 카테고리의 다른 글
Chapter05. CRUD 프로젝트 / 로그인 정보 활용하기 ( 세션 활용 3 ) (0) | 2023.03.27 |
---|---|
Chapter05. CRUD 프로젝트 / 로그인 정보 저장하기 ( 세션 활용 2 ) (0) | 2023.03.27 |
Chapter05. CRUD 프로젝트 / 아이디 기억하기 ( 쿠키 활용 ) (0) | 2023.03.27 |
Chapter05. CRUD 프로젝트 / 비밀번호 암호화하기 (0) | 2023.03.26 |
Chapter05. CRUD 프로젝트 / URL에서 포트 번호 없애기 (0) | 2023.03.26 |