<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>KH 커뮤니티</title>
<link rel="stylesheet" href="resources/css/main-style.css">
<script src="https://kit.fontawesome.com/4dca1921b4.js" crossorigin="anonymous"></script>
</head>
<body>
<main>
<header>
<!-- 클릭 시 메인페이지로 이동하는 로고 -->
<section>
<a href="#">
<img src="resources/images/logo.jpg" id="home-logo">
</a>
</section>
<!-- header의 두번째 자식 div -->
<section>
<article class="search-area">
<!-- form 내부 input 태그 값을 서버 또는 페이지로 전달 -->
<form action="#" name="search form">
<!-- fieldset : form 내부에서 input을 종류별로 묶는 용도로 많이 사용 -->
<fieldset>
<input type="search" id="query" name="query"
placeholder="검색어를 입력해주세요" autocomplete="off">
<!-- 검색 버튼 -->
<button type="submit" id="search-btn" class="fa-solid fa-magnifying-glass"></button>
</fieldset>
</form>
</article>
</section>
<section></section>
</header>
<nav>
<ul>
<li><a href=#>공지사항</a></li>
<li><a href=#>자유 게시판</a></li>
<li><a href=#>질문 게시판</a></li>
<li><a href=#>FAQ</a></li>
<li><a href=#>1:1문의</a></li>
</ul>
</nav>
<section class="content">
<section class="content-1">
loginMember : ${sessionScope.loginMember}
<hr>
message : ${sessionScope.message}
</section>
<section class="content-2">
<!-- if - else -->
<c:choose>
<%-- choose 내부에는 jsp 주석만 사용 --%>
<c:when test="${ empty sessionScope.loginMember }">
<!-- 절대경로 : /community/member/login -->
<!-- 상대경로 (index.jsp) 기준 -->
<form action="member/login" method="post" name="login-form">
<!-- 아이디(이메일)/비밀번호/로그인 버튼 영역 -->
<fieldset id="id-pw-area">
<section>
<input type="text" name="inputEmail" placeholder="아이디(이메일)" value="${cookie.saveId.value}">
<%-- 현재 페이지 쿠키 중 "saveId"의 내용을 출력 --%>
<input type="password" name="inputPw" placeholder="비밀번호">
</section>
<section>
<button>로그인</button>
</section>
</fieldset>
<!-- 회원가입, ID/PW 찾기 영역 -->
<article id="signup-find-area">
<a href="#">회원가입</a>
<span>|</span>
<a href="#">ID/PW 찾기</a>
</article>
<%-- 쿠키에 saveId가 있는 경우 --%>
<c:if test="${!empty cookie.saveId.value}">
<%-- chk 변수 생성(page scope) --%>
<c:set var="chk" value="checked"></c:set>
</c:if>
<label>
<input type="checkbox" name="saveId" ${chk}>아이디 저장
</label>
</form>
</c:when>
<%-- 로그인이 되어 있는 경우 --%>
<c:otherwise>
<article class='login-area'>
<!-- 회원 프로필 이미지 -->
<a href="#">
<img src="/community/resources/images/user.png" id="member-profile">
</a>
<!-- 회원 정보 + 로그아웃 버튼 -->
<div class="my-info">
<div>
<a href="#" id="nickname">${sessionScope.loginMember.memberNickname}</a>
<a href="/community/member/logout" id="logout-btn">로그아웃</a>
</div>
<p>
${sessionScope.loginMember.memberEmail}
</p>
</div>
</article>
</c:otherwise>
</c:choose>
</section>
</section>
</main>
<footer>
<p>Copyright © KH Information Educational Institute M-Class</p>
<article>
<a href="#">프로젝트 소개</a>
<span>|</span>
<a href="#">이용약관</a>
<span>|</span>
<a href="#">개인정보처리방침</a>
<span>|</span>
<a href="#">고객센터</a>
</article>
</footer>
</body>
</html>
package edu.kh.community.member.controller;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import edu.kh.community.member.model.service.MemberService;
import edu.kh.community.member.model.vo.Member;
@WebServlet("/member/login")
public class LoginServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// Post 방식 요청 시 문자 인코딩이 서버 기본값으로 지정
// -> 한글 깨짐 -> 문자 인코딩 변경 필요
// req.setCharacterEncoding("UTF-8");
// * 모든 doPost() 메소드에 인코딩 변경 코드를 작성해야 함.. (귀찮다)
// -> 모든 요청(전달 방식 가리지 않음) 시 req, resp에 문자 인코딩을 UTF-8로 변경
// -> 필터(Filter)
// 전달된 파라미터 변수에 저장
String inputEmail = req.getParameter("inputEmail");
String inputPw = req.getParameter("inputPw");
System.out.println(inputEmail);
System.out.println(inputPw);
// 파라미터를 VO에 세팅(롬복 확인)
Member mem = new Member();
mem.setMemberEmail(inputEmail);
mem.setMemberPw(inputPw);
try {
// 서비스 객체 생성
MemberService service = new MemberService();
// 이메일, 비밀번호가 일치하는 회원을 조회하는 서비스 호출 후 결과 반환
Member loginMember = service.login(mem);
// 로그인 성공/실패에 따른 처리 코드
// *** 로그인 ***
// ID/PW가 일치하는 회원 정보를 Session Scope에 세팅하는 것
// Session 객체 얻어오기
HttpSession session = req.getSession();
if(loginMember != null) { // 성공
// 회원 정보를 Session에 세팅
session.setAttribute("loginMember", loginMember);
// 특정 시간 동안 요청이 없으면 세션 만료
session.setMaxInactiveInterval(3600); // 3600초 == 1시간
// -> 초 단위로 작성
//===========================================================================
// 아이디 저장(Cookie)
/* Cookie : 클라이언트(브라우저)에서 관리하는 파일
*
* - 특정 주소 요청 시마다
* 해당 주소와 연관된 쿠키 파일을 브라우저가 알아서 읽어옴
* -> 읽어온 쿠키 파일 내용을 서버에 같이 전달함
*
* 생성 및 사용 방법
*
* 1) 서버가 요청에 대한 응답을 할 때
* 쿠키를 생성한 후 응답에 쿠키를 담아서 클라이언트에게 전달
*
* 2) 응답에 담긴 쿠키가 클라이언트에 파일 형태로 저장
*
* 3) 이후 특정 주소 요청 시
* 쿠키 파일을 브라우저가 찾아서 자동으로 요청에 실어서 보냄
*
* 4) 서버는 요청에 실려온 쿠키 파일을 사용함
*
* */
// 쿠키 객체 생성
// Cookie c = new Cookie("클라이언트쪽에 저장될 쿠키 이름", "쿠키 내용");
Cookie c = new Cookie("saveId", inputEmail);
// 아이디 저장이 체크된 경우
if(req.getParameter("saveId") != null) {
// 쿠키 파일을 30일 동안 유지
c.setMaxAge(60 * 60 * 24 * 30); // 30일(1초 단위)
} else {
// 쿠키 파일을 0초 동안 유지
// -> 기존에 존재하던 쿠키 파일에 유지 시간을 0초로 덮어씌움
// == 삭제하겠다는 소리
c.setMaxAge(0);
}
// 해당 쿠키 파일이 적용될 주소를 지정
c.setPath( req.getContextPath() );
// req.getContextPath() : 최상위 주소(/community)
// -> /community로 시작하는 주소에서만 쿠키 적용
// 응답 객체를 이용해서 클라이언트로 전달
resp.addCookie(c); // 코드가 해석되는 순간 바로 전달
//===========================================================================
} else { // 실패
session.setAttribute("message", "아이디 또는 비밀번호가 일치하지 않습니다.");
}
// 클라이언트 요청 -> 서버 요청 처리(Servlet) -> 응답 화면 만들어 줘(JSP 위임)
// 1. forward(요청 위임)
// - Servlet으로 응답 화면 만들기가 불편하기 때문에
// JSP로 req, resp 객체를 위임하여
// 요청에 대한 응답 화면을 대신 만듦
// *** 화면이 변경되어도 요청 주소가 유지된다 ***
// ex) 아이스 아메리카노 주세요 -> 주문 받음 -> 바리스타가 만든 커피
// 클라이언트 캐셔(Servlet) 응답 결과(JSP)
// 2. Redirect(재요청)
// - 현재 Servlet에서 응답 페이지를 만들지 않고
// 응답 페이지를 만들 수 있는
// 다른 요청의 주소로 클라이언트를 이동시킴(재요청)
// 클라이언트 재요청
// -> 기존 HttpServletRequest/Response 제거
// -> 새로운 HttpServletRequest/Response 생성
// ---> 리다이렉트 시 request 객체가 유지되지 않기 때문에
// 특정 데이터를 전달하거나 유지하고 싶으면
// Session 또는 application 범위에 세팅해야 한다!
// CGV 카페
// ex) 팝콘 주세요 -> 팝콘 파는 위치 알려 줌 -> (클) 팝콘 파는 곳으로 이동
// 클라이언트 캐셔(Servlet) 클라이언트의 다른 주소 재요청
resp.sendRedirect( req.getContextPath() );
// req.getContextPath() : 최상위 주소 (/community)
// forward
// req.getRequestDispatcher("../index.jsp").forward(req, resp);
}catch(Exception e) {
e.printStackTrace();
}
}
}
package edu.kh.community.member.controller;
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 LogoutServlet extends HttpServlet{
// a 태그를 이용한 요청은 무조건 GET 방식
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// *** 로그아웃 ***
// Session Scope에 세팅된 회원 정보를 없앰
// Session 얻어오기
HttpSession session = req.getSession();
// 1) Session에서 회원 정보만 없앰
// session.removeAttribute("loginMember");
// 2) Session 전체를 없애도 새로운 Session 만들기 (더 많이 사용되는 방법)
session.invalidate(); // 세션 무효화
// 현재 세션을 없앰 -> 자동으로 새로운 세션이 생성됨
// 메인 페이지로 돌아가기
// 1) forward : 로그아웃 응답 화면을 만든다. (부적절)
// 2) redirect : 메인 페이지 재요청 (이거!)
// 메인 페이지 == 최상위 주소(/community)로 요청했을 때 화면
resp.sendRedirect( req.getContextPath() );
}
}