✍ Today I Learned
- 톰캣 서버에 올라가 있는 프로젝트를 remove 하고, 02 프로젝트를 복사한 session 버전 프로젝트를 톰캣 서버에 add 한다.
- 충돌 방지를 위해 web.xml에 있는 display-name을 프로젝트와 같은 이름으로 바꿔준다.
[세션 Session]
- 세션(session)이란? 서버와 클라이언트의 연결을 유지시켜주는 방법이다. 쿠키는 클라이언트 브라우저에 생성되고 저장이 된다면, 세션은 웹서버 쪽 웹 컨테이너에 생성되고 저장이 된다.
- http 프로토콜은 브라우저에 어떤 요청을 하고 서버에서 응답을 하고 나면 해당 연결을 해제하는데, 쿠키와 세션을 이용해 해당 정보를 저장하면 연결을 유지시킬 수 있다.
- 세션은 웹 브라우저를 종료하거나, 프로그래밍적으로 세션을 종료하기 전까지 같은 창에서 열린 모든 페이지 내에서 같은 session 객체를 공유하게 된다.
- 주로 로그인 기능에 이용하지만, 세션만으로는 보안 상 안전하지 않다.
[분석하기]
- 회원 등록(비회원만 가능)
- 회원 리스트(MGR 계정만 열람 가능)
- 회원 정보의 수정/삭제(본인 계정만 가능)
- 상품 등록(회원만 가능)
- 상품 리스트(전체 가능)
- 상품 정보의 수정/삭제(회원만 가능)
- 로그인 메뉴(비회원에게만 보임)
- 로그아웃 / 현재 내 정보(회원에게만 보임)
[로그인 Login]
- nav에 Login 메뉴를 만들고 "/emp/login.em"으로 요청한 후 Controller에서 해당 요청을 "login.jsp"로 이동시킨다.
- 부트스트랩에서 forms의 템플릿을 가져와 loing.jsp를 작성한다. 이때, form 태그 내 action은 주소 값은 "./login_auth.em"으로, method 값은 "post"로 설정한다.("get" 방식으로 요청하면 주소창에 아이디와 비밀번호 노출됨)
- 유저는 아이디와 비밀번호를 입력하고, 해당 데이터가 DB에 있으면 VO객체로 만들어 꺼내온다. VO객체로 받는 이유는? 로그인된 회원의 추가 정보를 받아오기 위함이다.
- VO 객체에 Login용 생성자를 만든다. job에 따라 게시판 열람 권한이 다르기 때문에 job 정보도 받아올 것이다.
- 겹치는 오버 로딩이 있다면 파라미터의 순서를 바꿔 해결한다.
- 회원의 아이디로 한 명의 회원을 조회하기 때문에 selectOne 메서드를 오버 로딩하여 사용한다.
- 쿼리문의 where 조건절에 아이디와 비밀번호를 넣어 회원을 조회한 후 해당 객체를 세션에 다음과 같이 저장하여 "index.jsp"로 이동시킨다.
package action.emp;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import action.Action;
import domain.EmpVO;
import service.EmpService;
import service.EmpServiceImpl;
public class LoginAction implements Action {
private static Logger log = LoggerFactory.getLogger(LoginAction.class);
@Override
public void execute(HttpServletRequest req, HttpServletResponse res) {
int empno = Integer.parseInt(req.getParameter("empno"));
String pwd = req.getParameter("pwd");
EmpService esv = new EmpServiceImpl();
EmpVO evo = esv.login(empno, pwd);
if(evo != null) { // 로그인이 되면,
HttpSession ses = req.getSession(); // 세션 객체 생성
ses.setAttribute("ses", evo); // 세션에 evo 객체 정보를 저장
ses.setMaxInactiveInterval(60 * 10); // 세션 만료시간 설정 (초단위)
}else { // 로그인이 되지 않으면,
req.setAttribute("msg_login", 0); // 리퀘스트 객체로 0을 보냄
}
}
}
로그인 실패 메시지 출력
- DB에 해당하는 정보가 없어 로그인이 되지 않았을 경우, "index.jsp"에서 alert을 띄워준다.
- c:out 태그는 value에 작성한 값을 출력할 수 있다.
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<jsp:include page="header.jsp"/>
<jsp:include page="nav.jsp"/>
<h1>index.jsp</h1>
<script>
let msg_login = '<c:out value="${msg_login}"/>'; // '0'
if(msg_login === '0'){
alert('로그인 실패!');
}
</script>
<jsp:include page="footer.jsp"/>
회원/비회원의 nav를 다르게 출력
- 로그인이 성공했을 경우, 회원 전용 메뉴를 볼 수 있도록 "nav.jsp"를 다음과 같이 작성한다.
- c:set 태그는 변수를 생성해 값을 할당할 수 있다.
- c:if 태그는 조건에 따라 분기 처리를 할 수 있다.
- eq = equal, ne = not equal
- 로그인된 회원정보를 클릭하면 본인의 detail 페이지로 이동할 수 있도록 empno를 실어 요청한다.
....
<c:set var="ssevo" value="${ses }" scope="session"/>
<div class="collapse navbar-collapse" id="mynavbar">
<ul class="navbar-nav me-auto">
<c:if test="${ssevo eq null }">
<li class="nav-item">
<a class="nav-link" href="/emp/register.em">Emp Register</a>
</li>
</c:if>
<c:if test="${ssevo.job eq 'MGR' }"> <!-- job이 MGR인 회원만 열람 가능 -->
<li class="nav-item">
<a class="nav-link" href="/emp/list.em">Emp List</a>
</li>
</c:if>
<c:if test="${ssevo ne null }">
<li class="nav-item">
<a class="nav-link" href="/product/register.pd">Product Register</a>
</li>
</c:if>
<li class="nav-item">
<a class="nav-link" href="/product/list.pd">Product List</a>
</li>
<c:if test="${ssevo eq null }">
<li class="nav-item">
<a class="nav-link" href="/emp/login.em">Login</a>
</li>
</c:if>
<c:if test="${ssevo ne null }"> <!-- 로그인 된 회원에게 계정 정보 출력 -->
<li class="nav-item">
<a class="nav-link" href="/emp/detail.em?empno=${ssevo.empno }">${ssevo.ename }(${ssevo.job })</a>
</li>
</c:if>
</ul>
....
회원 정보의 수정/삭제(본인 계정만 가능)
- 회원 정보의 수정/삭제는 로그인된 본인의 계정만 가능하도록 emp의 "detail.jsp"를 다음과 같이 수정한다.
- 수정/삭제 버튼에 세션에 저장된 empno와 리퀘스트 객체로 전달된 empno가 같은지에 대한 조건문을 추가한다.
....
<c:if test="${ssevo.empno eq evo.empno}">
<a href="./modify.em?empno=${evo.empno }" class="btn btn-outline-warning">Modify</a>
<a href="./remove.em?empno=${evo.empno }" class="btn btn-outline-danger">Remove</a>
</c:if>
....
상품 정보의 수정/삭제(회원만 가능)
- 회원 정보와 마찬가지로 상품 정보의 수정/삭제는 로그인된 회원만 가능하도록 product의 "detail.jsp"를 다음과 같이 수정한다.
....
<c:if test="${ssevo ne null }">
<a href="./modify.pd?pno=${pvo.pno }" class="btn btn-outline-warning">Modify</a>
<a href="./remove.pd?pno=${pvo.pno }" class="btn btn-outline-danger">Remove</a>
</c:if>
....
상품 등록(회원만 가능)
- 상품 등록은 로그인된 회원만 가능하도록 하고, nav가 아닌 상품 리스트 화면의 버튼으로 이동시킨다.
....
<div class="d-flex">
<h2 class="me-3">Product List</h2>
<c:if test="${ssevo ne null }">
<a class="btn btn-primary" href="/product/register.pd">Register</a>
</c:if>
</div>
....
[로그아웃 Logout]
- 세션은 웹 브라우저당 1개씩 생성되어 웹 컨테이너에 저장된다.
- 서버에서 현재 세션의 정보를 제거하는 invalidate 메서드를 사용한다.
....
case "logout.em":
HttpSession ses = req.getSession();
ses.invalidate(); // 세션 정보 제거
req.setAttribute("msg_logout", 1); // 리퀘스트 객체로 1을 보냄
destPage = "/index.jsp"; // index.jsp 페이지로 이동
break;
....
- 로그인 실패 alert 띄운 것과 같은 방식으로 로그아웃 되었다는 alert을 띄운다.
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<jsp:include page="header.jsp"/>
<jsp:include page="nav.jsp"/>
<h1>index.jsp</h1>
<script>
let msg_login = '<c:out value="${msg_login}"/>'; // '0'
let msg_logout = '<c:out value="${msg_logout}"/>'; // '1'
if(msg_login === '0'){
alert('로그인 실패!');
}
if(msg_logout === '1'){
alert('로그아웃 되었습니다');
}
</script>
<jsp:include page="footer.jsp"/>
'📝 TIL' 카테고리의 다른 글
[TIL] JSP 웹페이지 만들기2 (Board) (0) | 2022.06.20 |
---|---|
[TIL] JSP 웹페이지 만들기(MyBatis, Member) (0) | 2022.06.17 |
[TIL] JSP로 CRUD 구현2 (0) | 2022.06.15 |
[TIL] JSP로 CRUD 구현 (0) | 2022.06.14 |
[TIL] JSP 개발 환경 설정 (0) | 2022.06.13 |