<로그인 >
메인 화면 배포 전이라 기존 메인을 로그인폼으로 했었는데 기존 배포된 메뉴바 include 해서 로그인 버튼 이용함
1. mainLogin.jsp
경로 노출되면 보안 위험 있으니 form만 띄워 줄 컨트롤러 부르기 위해 하단에 스크립트 구문 넣어 주고
로그인 버튼 onclick 속성 걸고
<Controller - Service - Dao - member-mapper - DB까지 갔다가 돌아왔을 때>
loginUser라는 변수에 회원 정보를 담고 있고, 메인 화면에서 닉넴 담긴 알림창 띄워 줘야 하니까
상단 스크립틀릿으로 loginUser 받고, contextPath 알려 주고, alertMsg 받고
login 안 된 상태라면 메뉴바에 로그인/회원가입 ----- login 된 상태라면 마이페이지/로그아웃 뜨도록 조건 넣기
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" import="com.insertcoin.member.model.vo.Member" %>
<%
Member loginUser = (Member)session.getAttribute("loginUser");
String contextPath = request.getContextPath();
String alertMsg = (String)session.getAttribute("alertMsg");
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>메인 화면</title>
<!-- CSS 스타일시트 -->
<link href="resources/css/memberLoginForm.css" rel="stylesheet">
<link href="resources/css/MainCss.css" rel="stylesheet">
<link href="resources/css/MainContentCss.css" rel="stylesheet">
<!-- jQuery 라이브러리 연결 -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.1/jquery.min.js"></script>
<!-- Bootstrap 프레임워크 연결 -->
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/css/bootstrap.min.css">
<!-- Popper JS -->
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js"></script>
<!-- Latest compiled JavaScript -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/js/bootstrap.bundle.min.js"></script>
</head>
<body>
<script>
var msg = "<%= alertMsg %>";
if(msg != "null") {
alert(msg);
<% session.removeAttribute("alertMsg"); %>
}
</script>
<!-- 전체 영역 -->
<div class="wrap">
<!-------------------------------------- 헤더 영역 -------------------------------------->
<!-- 헤더 영역 -->
<div class="header_container">
<!-- 헤더 로고 -->
<div class="header_logo_container">
<a href=""><img id="header_logo" src="resources/image/logo/insertcoin_logo.png" width="100%"></a>
</div>
<!-- 헤더 메뉴바 -->
<div id="header_menu">
<ul>
<li><a href="" class="main_menu">게임</a></li>
<li>
<a href="" class="main_menu">커뮤니티</a>
<ul>
<li><a href=""> 개발자 게시판</a></li>
<li><a href=""> 자유 게시판</a></li>
</ul>
</li>
<li>
<a href="" class="main_menu">고객센터</a>
<ul>
<li><a href=""> 공지사항</a></li>
<li><a href=""> FAQ</a></li>
</ul>
</li>
<% if (loginUser == null) { %>
<li>
<a id="login_menu" onclick="loginPage();">로그인</a>
<ul>
<li><a onclick="loginPage();"> 로그인</a></li>
<li><a> 회원가입</a></li>
</ul>
</li>
<% } else { %>
<li>
<a href="" class="main_menu">
<img src="resources/image/profile/profile_default.png" id="header_profile">
InsertCoin
</a>
<ul>
<li><a href=""> 마이페이지</a></li>
<li><a href="<%= contextPath %>/logout.me"> 로그아웃</a></li>
</ul>
</li>
<% } %>
</ul>
</div>
<!-- 헤더 검색 -->
<div class="header_search_container">
<form action="" class="header_search-bar">
<input type="search" name="search">
<button type="submit" id="header_search">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-search" viewBox="0 0 16 16">
<path d="M11.742 10.344a6.5 6.5 0 1 0-1.397 1.398h-.001c.03.04.062.078.098.115l3.85 3.85a1 1 0 0 0 1.415-1.414l-3.85-3.85a1.007 1.007 0 0 0-.115-.1zM12 6.5a5.5 5.5 0 1 1-11 0 5.5 5.5 0 0 1 11 0z"/>
</svg>
</button>
</form>
</div>
</div>
<div align="center" style="color:white; height:1000px; margin:auto;"><h1>메인 화면 영역</h1></div>
<div> 푸터 </div>
</div>
<script>
function loginPage() {
location.href = "<%= contextPath %>/loginForm.me";
}
</script>
</body>
</html>
2. LoginFormController.jsp
로그인 폼 띄워 주기만 할 controller
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 단순히 회원가입 폼을 띄워 줄 용도
request.getRequestDispatcher("views/member/memberEnrollForm.jsp").forward(request, response);
}
3. memberLoginForm.jsp
로그인 폼
getContextPath만 상단에 선언
로그인 버튼(submit 속성) 눌렀을 때 컨트롤러로 갈 수 있도록 form 태그에 action 속성 걸어 줌
action="<%= contextPath %>/login.me"
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" import="com.insertcoin.member.model.vo.Member" %>
<%
String contextPath = request.getContextPath();
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>로그인 화면</title>
<!-- CSS 스타일시트 -->
<link href="resources/css/memberLoginForm.css" rel="stylesheet">
<link href="resources/css/MainCss.css" rel="stylesheet">
<link href="resources/css/MainContentCss.css" rel="stylesheet">
<!-- jQuery 라이브러리 연결 -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.1/jquery.min.js"></script>
<!-- Bootstrap 프레임워크 연결 -->
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/css/bootstrap.min.css">
<!-- Popper JS -->
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js"></script>
<!-- Latest compiled JavaScript -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/js/bootstrap.bundle.min.js"></script>
</head>
<body>
<!-------------------------------------- 컨텐츠 영역 -------------------------------------->
<!-- 컨텐츠 영역 -->
<div class="content_container">
<!-- 로그인 창 -->
<form id="login_form" action="<%= contextPath %>/login.me" method="post">
<!-- 로고, 이메일, 비밀번호 입력 영역 -->
<div class="login_content">
<!-- 로그인 창 로고 -->
<div style="text-align:center;">
<img src="resources/image/logo/insertcoin_logo.png" alt="insert_coin_logo" id="login_logo">
</div>
<!-- 로그인 글자 -->
<div id="login_text"><h2>로그인</h2><hr></div>
<!-- 로그인 정보 입력 폼 -->
<table align="center" id="login_table">
<tr>
<th>이메일</th>
</tr>
<tr>
<th colspan="3">
<input type="email" name="memEmail" required>
</th>
</tr>
<tr>
<th>비밀번호</th>
</tr>
<tr>
<th colspan="3">
<input type="password" name="memPwd" required>
</th>
</tr>
<tr>
<!-- 로그인 버튼 -->
<th colspan="3"><button type="submit">로그인</button></th>
</tr>
</table>
<br>
<!-- 회원가입, 비밀번호 찾기 -->
<div align="center" id="etc">
<a onclick="enrollPage();">회원가입</a>
|
<a href="">비밀번호 찾기</a>
</div>
</div>
</form>
</div>
<script>
function enrollPage() {
location.href = "<%=contextPath %>/enrollForm.me";
}
</script>
</body>
</html>
4. LoginController
여기서부터 service, dao, member-mapper, DB까지 갔다가 돌아옴
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 로그인 정보는 POST 방식으로 처리해야 함 => 인코딩 처리
request.setCharacterEncoding("UTF-8");
// 요청 시 전달값을 꺼내기
// memEmail: 아이디 값(이메일)
String memEmail = request.getParameter("memEmail");
// memPwd: 비밀번호 값
String memPwd = request.getParameter("memPwd");
// memNickname: 닉네임값 (성공 메시지 표출 때 보여 주고자 함)
String memNickname = request.getParameter("memNickname");
// 요청 시 전달값들을 VO 객체로 가공
Member m = new Member();
m.setMemEmail(memEmail);
m.setMemPwd(memPwd);
// 가공한 VO 객체를 해당 요청을 처리하는 서비스 클래스의 메소드로 넘기기
Member loginUser = new MemberService().loginMember(m);
// 처리된 결과 응답 뷰 지정
if(loginUser == null) { // 로그인 실패 => 에러 문구를 담아서 에러 페이지로 응답하기
request.setAttribute("errorMsg", "로그인에 실패했습니다.");
RequestDispatcher view = request.getRequestDispatcher("views/common/errorPage.jsp");
view.forward(request, response);
} else { // 로그인 성공 => 응답 페이지에 loginUser 데이터 전달, 메인 페이지로 응답
HttpSession session = request.getSession();
session.setAttribute("loginUser", loginUser);
session.setAttribute("alertMsg", loginUser.getMemNickname() + "님! 오늘도 즐거운 게임 하세요!");
response.sendRedirect(request.getContextPath());
}
}
<로그아웃>
1. LogoutController 서블릿 생성 (/logout.me)
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 잘 가라고 인사하고
HttpSession session = request.getSession();
session.setAttribute("alertMsg", "성공적으로 로그아웃되었습니다. 내일도 게임하러 오세요!");
// 사용자의 아이디와 비밀번호는 소중하니까 확실하게 지워봄
request.getSession().removeAttribute("loginUser");
response.sendRedirect(request.getContextPath());
}
2. main 화면의 로그아웃 버튼에 적용
<li><a href="<%= contextPath %>/logout.me"> 로그아웃</a></li>
<회원가입>
1. 메인 폼과 로그인 폼 회원가입 버튼 onclick 속성 걸고 script 구문
메인화면 회원가입 버튼, 로그인 폼에서의 회원가입 버튼 모두!
🤔 로그인 폼에서 회원가입 버튼 누를 때 밋밋해서 pointer: cursor; font-sylte: underline; 주고 싶은데 안 먹히네,,, 나중에 계속
<li><a onclick="enrollPage();"> 회원가입</a></li>
<script>
function enrollPage() {
location.href = "<%=contextPath %>/enrollForm.me";
}
</script>
2. MemberEnrollFormController 서블릿 생성
회원가입 폼을 띄워 줄 용도
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 단순히 회원가입 폼을 띄워 줄 용도
request.getRequestDispatcher("views/member/memberEnrollForm.jsp").forward(request, response);
}
3. memberEnrollForm.jsp 생성
회원가입 폼 틀 만들어 줌
4. MemberEnrollController 서블릿 생성
진짜 회원가입 할 때 쓰일 컨트롤러
뽑아야 할 값 뽑고 멤버 변수에 담기
5. 회원가입용 Member 생성자 생성
6. 요청값을 Service-> Dao -> member-mapper.xml -> DB 넘긴 뒤에
-> Dao -> Service로 다시 가지고 오기
lib 폴더에 제이쓴 & 쥐쓴 .jar 추가
😱 인증번호 요청 버튼 -> 중복 확인 후 중복 아니면 인증번호 보내기
😱 메일 최대 길이 30자 제한
<메일 중복 확인 & 포맷 제한>
1. memberEnrollForm.jsp
이메일 30자 제한
회원가입 폼에서 인증번호 요청 버튼을 눌렀을 때 중복확인부터 한 뒤 인증번호 보내기 때문에 onclick 속성에 선언적 함수 걸기
<tr>
<th>이메일</th>
</tr>
<tr>
<th colspan="4">
<input type="email" name="memEmail" maxlength="30" required>
</th>
<td><button class="table_button" onclick="emailCheck();">인증번호 요청</button></td>
</tr>
<script>
function emailCheck() {
var $memEmail = $("#enroll_table input[name=memEmail]");
$.ajax({
url : "emailCheck.me",
data : {checkEmail : $memEmail.val()},
success : function(result) {
},
error : function () {
console.log("이메일 중복 체크용 ajax 통신 실패!");
}
});
}
</script>
script에서 "키 : 밸류"로 이메일창(name: memEmail)에 입력된 데이터를 emailCheck.me(컨트롤러)로 보냈음
2. EmailCheckController (/emailCheck.me)
니가 보낸 키값에 request.getParameter을 사용해서 밸류 넣어 줄게!
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// checkEmail이라는 변수에 든 value값 뽑기
String checkEmail = request.getParameter("checkEmail");
// 전달값인 밸류를 서비스로 넘겨서 요청 처리 후 결과 받기
// 응답 데이터는 1개만 넘기기 때문에 JSON 필요 없이 Ajax로 해결 가능
// 넘겨 주기
int count = new MemberService().emailCheck(checkEmail);
// 응답 데이터에 한글이 있다면 깨질 수도 있으니 문서 타입과 인코딩 방식 알려 주기
response.setContentType("text/html; charset=UTF-8");
// DB까지 다녀온 count에 중복 이메일 값이 있다면 1, 없다면 0이 담겨 있을 것
if(count > 0) {
response.getWriter().print("possible");
} else {
response.getWriter().print("impossible");
}
}
3. MemberService
// 이메일 중복체크용 서비스
public int emailCheck(String emailCheck) {
Connection conn = JDBCTemplate.getConnection();
int count = new MemberDao().emailCheck(conn, emailCheck);
JDBCTemplate.close(conn);
return count;
}
4. MemberDao
public int emailCheck(Connection conn, String checkEmail) {
// SELECT문 => ResultSet 객체 (숫자 1개)
// 필요한 변수 세팅
int count = 0;
PreparedStatement pstmt = null;
ResultSet rset = null;
String sql = prop.getProperty("emailCheck");
try {
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, checkEmail);
rset = pstmt.executeQuery();
if(rset.next()) {
count = rset.getInt("COUNT(*)");
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
JDBCTemplate.close(rset);
JDBCTemplate.close(pstmt);
}
return count;
}
5. member-mapper.xml
<entry key="emailCheck">
SETLECT COUNT(*)
FROM MEMBER
WHERE MEM_EMAIL = ?
</entry>
😱 인증 버튼 => 일치하면 submit
<인증...어케하지>
ㄷ
😱 비밀번호.val() == 비밀번호 확인.val() 일 때만 넘어가게 조건 걸기
😱 비밀번호 8~16자리 영어 대소문자, 숫자, 특수문자
<비밀번호 일치 확인>
ㄷ
😱 닉네임 중복 확인
😱 닉네임 2~10자리의 한글, 영문, 숫자, 특수문자
<닉네임 중복 확인 & 포맷 제한>
ㄷ