본 포스팅의 예제는 STS 또는 Eclipse를 사용하지 않고 Intellij를 통해 구현하고 있습니다.
그래서 기존의 STS(Spring Tool Studio)에서 생성된 Spring 프로젝트의 스프링 관련 설정 파일명과
프로젝트 구조가 약간 다를 수 있습니다.Intellij 스프링 mvc 프로젝트 생성 포스팅을 참고해주시면 감사하겠습니다.
Spring-MVC 기본 개념 및 테스트 예제 관련 포스팅 링크
순서 | 포스팅 제목 |
1 | Intellij에서 Spring MVC Project 생성하기 |
2 | Spring MVC - MariaDB 연결테스트 |
3 | Spring MVC - Mybatis 설정 및 테스트 |
4 | SpringMVC 구조 |
5 | SpringMVC + Mybatis |
6 | Spring MVC Controller 작성 연습 |
Spring-MVC 게시판 예제 이전 포스팅 링크
1. HttpSession과 로그인
웹에서 로그인을 하는 가장 기본적인 방식은 HttpSession 객체를 이용해서 사용자의 정보를 보관하고, 필요한 경우 사용하거나 수정하는 방식입니다.
HttpSession의 동작은 세션 쿠키를 통해 이루어지며 서버는 접속한 브라우저에게 고유한 세션쿠키를 전달하고, 매번 브라우저에서 서버를 홏풀 떄 세션 쿠키를 가지고 다니기 때문에, 이를 마치 열쇠처럼 사용해서 필요한 데이터를 보관하게 됩니다.
세션쿠키가 열쇠라면 HttpSession은 열쇠가 필요한 잠금장치가 되어있는 상자와 유사합니다. 이 상자들이 모여있는 공간을 세션 저장소 (Session Repository)라고 하는데 너무나 만ㅇ흔 세션이 존재하면 서버의 성능에 영향을 미치기 떄문에 서버는 일정시간 이상 사용되지 않는 상자들을 정리하는 기능을 가지고 있습니다. web.xml에서 HttpSession의 timeout을 지정할 수 있습니다.
session을 이용하는 방식의 핵심은 HttpSession을 이용해서 원하는 객체를 보관할 수 있다는 점입니다. 사용자는 항상 열쇠에 해당하는 세션쿠키를 가지고 접근하고, 서버의 내부에 상자가 필요한 객체를 보관하기 떄문에 안전하다는 장점을 가지고 있습니다.
session에 보관된 객체는 JSP에서 EL을 이용해서 자동으로 추적하는 방식을 사용하게 됩니다. 예를 들면 $(sessionUser}은 page -> request -> session -> application의 순서대로 원하는 데이터를 검색 하게 됩니다. 이와 같은 방식으로 동작하기 떄문에 JSP 를 개발하는 개발자는 자신이 사용하는 변수가 request에 존재 하는것인지 아니면 session에 존재하는 것인지 고민하지 않아도 됩니다.
1.1 HttpSession
아래의 내용은 위의 Servlet API에서 HttpSession에 대한 애용을 번역하고 정리한 내용입니다.
HttpSession은 둘 이상의 페이지의 요청 또는 웹사이트를 방문한 사용자를 식별하고 해당 사용자에 대한 정보를 저장하는 방법을 제공합니다.
- 서블릿 컨테이너는 Http 클라이언트와 Http 서버 사이의 세션을 만드는데 사용 합니다.
- Session은 두명 이상의 사용자 연결 또는 페이지 요청을 통해 지정된 기간 동안 유지 됩니다.
- Session은 보통 웹사이트를 여러번 방문하는 하나의 사용자에 해당됩니다.
- 서버는 쿠키를 사용하거나 URL 다시쓰기 등과 같은 여러가지 방법으로 session을 유지 할 수 있습니다
HttpSession은 서블릿이 다음과 같은 작업을 수행하도록 허용 합니다.
- Session 식별자, 생성시간, 마지막 접근 시가나과 같은 세션에 대한 정보를 조작하고 볼 수 있습니다.
- 객체를 Session에 바인딩하여 여러 사용자 연결에서 사용자 정보가 유지되도록 합니다.
어플리케이션이 Session에 객체를 저장하거나 제거할 떄, Session은 객체가 HttpSessionBindingListener 인터페이스 구현여부를 확인합니다. 이 경우에 서블릿은 Session에 바인딩 되거나 바인딩 해제되었음을 바인딩 메서드의 실행이 완료된 후에 알려줍니다. 해제되거나 만료된 Session은 Session이 해제되거나 만료된 후에 알려줍니다.
컨테이너가 분산 컨테이너 설정에서 VM간의 세션을 옮겨갈 떄 HttpSessionActivationListener 인터페이스를 구현하는 모든 Session의 속성을 알려줍니다.
서블릿은 쿠키를 의도적으로 해제할 떄와 같이 클라이언트가 Session 참여하지 않는 경우를 처리 할 수 있어야 합니다. 클라이언트가 Session에 참여 할 때까지 isNew() 메서드는 true를 반환합니다. 만약 클라이언트가 Session에 참여하지 않기로 선택한 경우에는 getSession() 메서드는 각 요청에 대한 다른 Session를 반환하고, isNew() 메서드는 항상 true를 반환 합니다.
Session의 정보는 현재 웹 어플리케이션(Servlet Context)의 범위만 지정되기 떄문에 하나의 Context에 저장된 정보는 직접적으로 다른 Context에서는 볼 수 없습니다.
2. 로그인 구현
2.1 로그인 처리를 위한 DTO 클래스 작성
기본클래스/user/domain 패키지안에 LoginDTO 클래스를 생성하고, 아래와 같이 코드를 작성 해 줍니다. LoginDTO의 용도는 로그인 화면으로부터 전달되는 회원의 데이터(아이디, 비밀번호)를 수집하는 용도로 사용 됩니다.
public class LoginDTO {
private String user_id; // 아이디
private String user_pw; // 비밀번호
private boolean useCookie; // 로그인 유지 여부
private boolean saveCookie; // 아이디 저장 여부
// Constructor getter setter toString 생략
}
VO(Value Object) 와 DTO(Data Transfer Object) 차이점
일반적으로 컨트롤러에 전달되는 데이터를 수집하는 용도로 VO를 사용하는 경우도 있고, DTO을 사용하는 경우도 있는데 두 용어에 대해서 공통점과 차이점에 대해 알아보겠습니다.
공통점 | 차이점 |
DTO와 VO의 용도는 데이터 수집과 전달에 사용 할 수 있다 | VO의 경우 보다 데이터베이스와 거리가 가깝기 떄문에 VO는 테이블 구조를 이용해서 작성되는 경우가 많다. |
파라미터나 리턴 타입으로 사용하는 것이 가능하다. | DTO의 경우 화면에 거리가 가깝기 떄문에 화면에서 전달되는 데이터를 수집하는 용도로 사용하는 경우가 많다. |
2.2 회원 영속 계층(Persistence Tier) 구현
UserDAO 인터페이스에 로그인 메서드를 추가하고, UserDAOImpl 클래스에서 로그인 메서드를 구현합니다.
// 로그인
public UserVo selectByIdAndPw(LoginDTO loginDto);
// 로그인
@Override
@LogException
public UserVo selectByIdAndPw(LoginDTO dto) {
return sqlSession.selectOne(NAMESPACE + ".selectByIdAndPw", dto);
}
그리고 UserSQLMapper.xml에서 회원의 아이디로 회원정보를 select하는 쿼리를 작성해줍니다.
<!-- 로그인 -->
<select id="" resultType="UserVo">
select * from eden_user where user_id = #{user_id}
</select>
2.3 회원 비지니스 계층 (Business Tier) 구현
UserService 인터페이스와 UserServiceImpl 클래스에서 로그인 메서드를 아래와 같이 구현합니다.
// 로그인
public UserVo login(LoginDTO dto);
// 로그인
@Override
@LogException
public UserVo login(LoginDTO dto) {
return userDAO.selectByIdAndPw(dto);
}
2.4 로그인 컨트롤러 작성
서비스 계층까지 구현이 완료 되었는데 나머지는 컨트롤러와 인터셉터를 적용하는 작업을 진행 해야 합니다. 이 떄 가장 중요한 것이 컨트롤러에서 HttpSession 객체를 처리할 것인지 아니면 인터셉터에서 HttpSession을 처리 할 것인지 정해야 합니다.
스프링 MVC는 컨트롤러에서 필요한 모든 자원을 파라미터에서 수집해서 처리하기 떄문에 HttpServletRequest나 HttpSession과 같은 자원들 역시 파라미터로 처리해도 문제가 없다.
UserControler 클래스 에는 login 페이지에 접속하는 url 매핑 을 추가해주고 RestUserController에는 로그인을 처리하는 url 매핑을 추가해주세요
// 로그인 페이지
@GetMapping(value = "login")
public String login() {
return "user/login";
}
// 유저로그인
@PostMapping(value = "userLoginProcess")
@LogException
public HashMap<String, Object> userLoginProcess(LoginDTO loginDto, HttpSession session) {
HashMap<String, Object> data = new HashMap<String, Object>();
UserVo sessionUser = userService.login(loginDto);
if (sessionUser != null) {
String state = sessionUser.getUser_status();
if (state.equals("Inactive")) {
data.put("result", "out");
} else if (!BCrypt.checkpw(loginDto.getUser_pw(), sessionUser.getUser_pw())) {
data.put("result", "fail");
} else {
data.put("result", "success");
session.setAttribute("sessionUser", sessionUser);
}
}
return data;
}
위 코드에서 집중해서 봐야 할 것은 로그인처리 메서드(userLoginProcess())인데 처리 과정을 정리하면 아래와 같습니다.
- 화면으로부터 받은 데이터(회원아이디, 비밀번호) 중에서 아이디를 통해 select한 회원 정보를 변수 sessionUser에 담습니다.
- sessionUser가 널이 아닐때 코드를 실행 합니다.
- user_status 가 활성화 상태가 아닐 경우 키 : result 값 : "out" 으로 data 에 추가 해준다.
- 비밀번호를 BCrypt.checkpw()를 통해 검증해서 맞지 않으면 키 : result 값 : "fail" 을 추가 해준다.
- 비밀번호가 일치하면 키 : result 값 : success 로 data에 추가해주고 model에 sessionUser를 user란 이름의 변수로 저장한다.
2.5 로그인 화면 구현
login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ include file="../include/head.jsp" %>
<html>
<body class="hold-transition skin-green-light sidebar-mini" oncopy="return false" oncut="return false"
onpaste="return false">
<div class="wrapper">
<%@ include file="../include/top_menu.jsp" %>
<%@ include file="../include/left_menu.jsp" %>
<div class="content-wrapper">
</div>
<%@ include file="../include/footer.jsp" %>
</div>
<div class="modal fade" id="userLoginModal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span></button>
<h4 class="modal-title">로그인 페이지</h4>
</div>
<div class="modal-body" data-rno>
<div class="row mt-1">
<div class="col">
<div class="row mt-1">
<div class="col">
<label for="inputId">아이디</label>
</div>
</div>
<div class="row mt-1">
<div class="col">
<input type="text" class="form-control" id="inputId" name="user_id"
placeholder="아이디를 입력해주세요">
</div>
</div>
<div class="row mt-1">
<div class="col">
<div class="col">
<input type="password" class="form-control" id="inputPw" name="user_pw"
placeholder="비밀번호를 입력해주세요">
</div>
</div>
</div>
<div class="row mt-1">
<div class="col">
<input type="checkbox" class="form-check-input" id="saveIdBox">ID저장
<input type="checkbox" class="form-check-input" id="userCookie"> 자동로그인
</div>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<div class="row mt-1">
<div class="col">
<button type="button" class="btn btn-danger btn-xs pull-left" data-dismiss="modal">닫기</button>
<button type="button" class="btn btn-primary btn-xs pull-right infoModBtn" id="loginButton"><i
class="glyphicon glyphicon-log-in"></i>로그인
</button>
</div>
</div>
<div class="row mt-1">
<div class="col pull-right">
<a href="#" class="btn btn-primary btn-xs" data-toggle="modal"
data-target="#userIdFindModel"><b>아이디 찾기</b></a>
<a href="#" class="btn btn-primary btn-xs" data-toggle="modal"
data-target="#userPwFindModel"><b>비밀번호 찾기</b></a>
</div>
</div>
</div>
</div>
</div>
</div>
<%@ include file="../include/plugin_js.jsp" %>
<script type="text/javascript">
$(document).ready(function () {
$("#userLoginModal").modal('show');
});
</script>
</body>
</html>
top_menu.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<header class="main-header">
<a href="/" class="logo">
<span class="logo-mini"><b>S</b>E</span>
<span class="logo-lg"><b>Spring</b> - Examples</span>
</a>
<nav class="navbar navbar-static-top" role="navigation">
<a href="#" class="sidebar-toggle" data-toggle="push-menu" role="button">
<span class="sr-only">Toggle navigation</span>
</a>
<div class="navbar-custom-menu">
<ul class="nav navbar-nav">
<c:choose>
<c:when test="${!empty sessionUser }">
<li class="dropdown user user-menu">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
<img src="../resources/dist/img/profile/${sessionUser.user_image}" class="user-image"
alt="User Image">
<span class="hidden-xs">${sessionUser.user_nickname}</span>
</a>
<ul class="dropdown-menu">
<li class="user-header">
<img src="../resources/dist/img/profile/${sessionUser.user_image}" class="img-circle"
alt="User Image">
<p>
<small>
가입일자 : <fmt:formatDate value="${sessionUser.user_join_date}"
pattern="yyyy-MM-dd"/>
</small>
<small>
최근로그인일자 : <fmt:formatDate value="${sessionUser.user_last_connection_date}"
pattern="yyyy-MM-dd a HH:mm"/>
</small>
</p>
</li>
<li class="user-body">
<div class="row">
<div class="col-xs-4 text-center">
<a href="#">게시글</a>
</div>
<div class="col-xs-4 text-center">
<a href="#">추천글</a>
</div>
<div class="col-xs-4 text-center">
<a href="#">북마크</a>
</div>
</div>
</li>
<li class="user-footer">
<div class="pull-left">
<a href="${path}/user/profile" class="btn btn-primary btn-flat"><i
class="fa fa-info-circle"></i><b> 내 프로필</b></a>
</div>
<div class="pull-right">
<a type="button" id="logoutButton" class="btn btn-primary btn-flat"><i
class="glyphicon glyphicon-log-out"></i><b> 로그아웃</b></a>
</div>
</li>
</ul>
</li>
</c:when>
<c:otherwise>
<li class="dropdown user user-menu">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
<img src="../resources/dist/img/default-user-image.jpg" class="user-image"
alt="User Image">
<span class="hidden-xs">회원가입 또는 로그인</span>
</a>
<ul class="dropdown-menu">
<li class="user-header">
<img src="../resources/dist/img/default-user-image.jpg" class="img-circle"
alt="User Image">
<p>
<b>회원가입 또는 로그인해주세요</b>
<small></small>
</p>
</li>
<li class="user-footer">
<div class="pull-left">
<a href="${path}/user/register" class="btn btn-primary btn-flat"><i
class="fa fa-user-plus"></i><b> 회원가입</b></a>
</div>
<div class="pull-right">
<a href="../user/login" class="btn btn-primary btn-flat"><i
class="glyphicon glyphicon-log-in"></i><b> 로그인</b></a>
</div>
</li>
</ul>
</li>
</c:otherwise>
</c:choose>
</ul>
</div>
</nav>
</header>
relatedUser.js
window.addEventListener("DOMContentLoaded", function () {
$("#joinIdInput").keyup(function () {
var value = $(event.target).val();
var num = value.search(/[0-9]/g);
var eng = value.search(/[a-z]/ig);
if (value.length < 5 || value.length > 10) {
$("#alertId").css({
"color": "red",
"font-size": "10px"
});
$("#alertId").text("! 아이디는 5자리이상 10자리 이하여야 합니다.")
} else if (value.replace(/\s| /gi, "").length == 0) {
$("#alertId").css({
"color": "red",
"font-size": "10px"
});
$("#alertId").text("! 아이디에 공백은 사용할 수 없습니다.")
} else if (num < 0 || eng < 0) {
$("#alertId").css({
"color": "red",
"font-size": "10px"
});
$("#alertId").text("! 아이디는 영어+숫자로 이루어져야 합니다.")
} else {
$.ajax({
type: "post",
url: "./isExistId",
data: {
user_id: $("#joinIdInput").val()
},
dataType: "json",
//contentType : "application/x-www-form-urlencoded", // post
success: function (data) {
if (data.result == "fail") {
$("#alertId").css({
"color": "red"
});
$("#alertId").text("! 이미 사용중인 아이디입니다.")
} else {
$("#alertId").css({
"color": "black"
});
$("#alertId").text("✔ 사용 가능한 아이디입니다.")
}
}
});
}
});
$("#changePassword").keyup(function () {
var value = $(event.target).val();
var num = value.search(/[0-9]/g);
var eng = value.search(/[a-z]/ig);
var spe = value.search(/[`~!@@#$%^&*|₩₩₩'₩";:₩/?]/gi);
if (value.length < 8 || value.length > 30) {
$("#alterPassword").css({
"color": "red",
"font-size": "10px"
});
$("#alterPassword").text("! 비밀번호는 8자리이상 30자리 이하여야 합니다.")
} else if (value.replace(/\s| /gi, "").length == 0) {
$("#alterPassword").css({
"color": "red",
"font-size": "10px"
});
$("#alterPassword").text("! 비밀번호에 공백은 사용할 수 없습니다.")
} else if (num < 0 || eng < 0 || spe < 0) {
$("#alterPassword").css({
"color": "red",
"font-size": "10px"
});
$("#alterPassword").text("! 비밀번호는 영어+숫자+특수문자로 이루어져야 합니다.")
} else {
$("#alterPassword").css({
"color": "black",
"font-size": "10px"
});
$("#alterPassword").text("✔ 사용가능한 비밀번호입니다.");
}
});
$("#confirmPassword").keyup(function () {
var value = $("#confirmPassword").val();
if (value != $("#changePassword").val()) {
$("#alterPassword2").css({
"color": "red",
"font-size": "12px"
});
$("#alterPassword2").text("! 비밀번호가 일치하지 않습니다.")
return;
}
;
$("#alterPassword2").css({
"color": "black",
"font-size": "10px"
});
$("#alterPassword2").text("✔ 비밀번호가 일치합니다.");
});
$("#userNickName").keyup(function () {
var value = $(event.target).val();
var txt = value.search(/[가-힣]/g);
if (value.length < 1 || value.length > 10) {
$("#alertNickname").css({
"color": "red",
"font-size": "10px"
});
$("#alertNickName").text("! 닉네임은 1자리이상 10자리 이하여야 합니다.")
} else if (value.replace(/\s| /gi, "").length == 0) {
$("#alertNickname").css({
"color": "red",
"font-size": "10px"
});
$("#alertNickname").text("! 닉네임에 공백은 사용 할 수 없습니다.")
} else if (txt < 0) {
$("#alertNickname").css({
"color": "red",
"font-size": "10px"
});
$("#alertNickname").text("! 닉네임은 한글만 입력 가능합니다.")
} else {
$.ajax({
type: "post",
url: "./isExistNickName",
data: {
user_nickname: $("#userNickName").val()
},
dataType: "json",
success: function (data) {
if (data.result == "fail") {
$("#alertNickName").css({
"color": "red",
"font-size": "10px"
});
$("#alertNickName").text("! 이미 사용중인 닉네임 입니다.")
} else {
$("#alertNickName").css({
"color": "black",
"font-size": "10px"
});
$("#alertNickName").text("✔ 사용 가능한 닉네임입니다.")
}
}
});
}
});
$("#userPhone").keyup(function () {
var value = $(event.target).val();
var phone = $("#userPhone").val();
var regex = new RegExp("^01([0|1|6|7|8|9])-?([0-9]{3,4})-?([0-9]{4})$");
if (value.length < 13 || value.length > 13) {
$("#alertPhone").css({
"color": "red",
"font-size": "10px"
});
$("#alertPhone").text("! 휴대폰번호는 하이폰포함 13글자여야 됩니다.");
} else if (!regex.test(phone)) {
$("#alertPhone").css({
"color": "red",
"font-size": "10px"
});
$("#alertPhone").text("! 휴대폰번호 정규식에 맞게끔 작성해주세요");
} else {
$.ajax({
type: "post",
url: "./isExistPhone",
data: {
user_phone: $("#userPhone").val()
},
dataType: "json",
success: function (data) {
if (data.result == "fail") {
$("#alertPhone").css({
"color": "red",
"font-size": "10px"
});
$("#alertPhone").text("! 이미 사용중인 휴대폰 번호 입니다.")
} else {
$("#alertPhone").css({
"color": "black",
"font-size": "10px"
});
$("#alertPhone").text("✔ 사용 가능한 휴대폰번호입니다.");
}
}
});
}
});
$("#userEmail").keyup(function () {
var value = $(event.target).val();
var email = $("#userEmail").val();
var regex = new RegExp("^[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*@[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*.[a-zA-Z]{2,3}$");
if (!regex.test(email)) {
$("#alertEmail").css({
"color": "red",
"font-size": "10px"
});
$("#alertEmail").text("! 이메일의 정규식에 맞게끔 작성 부탁드립니다. abc@gmail.com");
} else {
$.ajax({
type: "post",
url: "./isExistEmail",
data: {
user_email: email
},
dataType: "json",
success: function (data) {
if (data.result == "fail") {
$("#alertEmail").css({
"color": "red",
"font-size": "10px"
});
$("#alertEmail").text("! 이메일이 이미 사용중입니다.");
} else {
$("#alertEmail").css({
"color": "black",
"font-size": "10px"
});
$("#alertEmail").text("✔ 사용 가능한 이메일주소입니다.");
$("#checkEmailButton").attr("disabled", false);
}
}
});
}
});
var code = "";
$("#checkEmailButton").click(function () {
$.ajax({
type: "post",
url: "./checkEmail",
data: {
user_email: $("#userEmail").val()
},
dataType: "json",
success: function (data) {
if (data.result == "error") {
alert("서버와 통신중 에러가 발생했습니다.");
$("#alertCertified").css({
"color": "rad",
"font-size": "10px"
});
$("#alertCertified").text("! 서버 통신중 에러가 발생 하였습니다.");
} else {
alert("인증번호 발송이 완료되었습니다. 입력한 이메일에서 인증번호 확인을 해주세요.");
$("#alertCertified").text("! 인증번호를 입력해주세요.")
$("#alertCertified").css({
"color": "red",
"font-size": "10px"
});
code = data.code;
$("#checkEmail").attr("disabled", false);
$("#checkEmailButton").attr("disabled", true);
}
}
});
});
$("#checkEmail").keyup(function() {
if ($("#checkEmail").val().length != 6) {
$("#alertCertified").text("! 인증번호가 일치하지 않습니다. 다시 확인해주시기 바랍니다.")
$("#alertCertified").css({
"color": "red",
"font-size": "10px"
});
} else if ($("#checkEmail").val() == code) {
$("#alertCertified").text("✔ 메일인증이 완료되었습니다.")
$("#alertCertified").css({
"color": "green",
"font-size": "10px"
});
$("#checkEmail").attr("disabled", true);
$("#joinButton").attr("disabled", false);
$("#userEmail").attr("disabled", false);
$("#updateInfo").attr("disabled", false);
}
});
$("#joinButton").click(function() {
if ($("#alertId").text() != "✔ 사용 가능한 아이디입니다.") {
alert("아이디 중복 확인을 해주세요.");
return;
}
if ($("#alertNickName").text() != "✔ 사용 가능한 닉네임입니다.") {
alert("닉네임 중복확인을 해주세요");
return;
}
if ($("#alertPhone").text() != "✔ 사용 가능한 휴대폰번호입니다.") {
alert("휴대폰번호 중복 확인을 해주세요.");
return;
}
if ($("#alertEmail").text() != "✔ 사용 가능한 이메일주소입니다.") {
alert("이메일 중복 확인을 해주세요");
return;
}
if($("#alertCertified").text() != "✔ 메일인증이 완료되었습니다.") {
alert("메일 인증을 해주세요");
return;
}
$("#insertForm").submit();
alert("회원가입이 완료 되었습니다.");
});
/* 로그인 Ajax 호출 부분 */
$("#inputId").keypress(function (e) {
if (e.keyCode == 13) {
$("#loginButton").click();
}
});
$("#inputPw").keypress(function (e) {
if (e.keyCode == 13) {
$("#loginButton").click();
}
});
var userInputId = getCookie("userInputId");
var setCookieYN = getCookie("setCookieYN");
if (setCookieYN == 'Y') {
$("#saveIdBox").prop("checked", true);
} else {
$("#saveIdBox").prop("checked", false);
}
$("#inputId").val(userInputId);
$("#loginButton").click(function () {
var id = $("#inputId").val();
var pw = $("#inputPw").val();
if (id.replace(/\s| /gi, "").length == 0) {
$("#alertId").css({
"color": "red"
});
$("#alertId").text("! 아이디를 입력해주세요.")
return;
}
if (pw.replace(/\s| /gi, "").length == 0) {
$("#alertPw").css({
"color": "red"
});
$("#alertPw").text("! 패스워드를 입력해주세요.")
return;
}
$.ajax({
type: "post",
url: "../user/userLoginProcess",
data: {
user_id: $("#inputId").val(),
user_pw: $("#inputPw").val(),
useCookie: $("#userCookie").prop("checked"),
saveCookie: $("#saveIdBox").prop("checked")
},
dataType: "json",
// contentType : "application/x-www-form-urlencoded", // post
success: function (data) {
if (data.result == "success") {
alert("로그인에 성공 하였습니다.");
location.href = data.destination;
} else if (data.result == "out") {
if (confirm("비활성화된 계정입니다. 계정 활성화 페이지로 이동하시겠습니까?") == true) {
location.href = "../user/userLogoutProcess";
location.href = "../user/userRecoveryPage";
} else {
location.href="../main/main";
}
} else {
alert("로그인에 실패하였습니다. 아이디와 비밀번호를 확인해 주세요.");
}
}
});
});
$("#logoutButton").click(function () {
if (confirm("로그아웃 하시겠습니까?")) {
$.ajax({
type: "post",
url: "../user/userLogoutProcess",
// contentType : "application/x-www-form-urlencoded", // post
dataType: "json",
success: function (data) {
location.reload();
}
});
}
});
});
/* 로그인 부분 */
function showLoginModal() {
$("#userLoginModal").modal('show');
}
//쿠키값 가져오기
function getCookie(cookie_name) {
var x, y;
var val = document.cookie.split(';');
for (var i = 0; i < val.length; i++) {
x = val[i].substr(0, val[i].indexOf('='));
y = val[i].substr(val[i].indexOf('=') + 1);
x = x.replace(/^\s+|\s+$/g, ''); // 공백 제거
if (x == cookie_name) {
return unescape(y);
}
}
}
2.6 아이디 저장을 위한 쿠키 생성 및 처리
아이디 저장 처리를 위해 RestUserController 소스를 아래와 같이 수정해주세요
// 유저로그인
@PostMapping(value = "userLoginProcess")
@LogException
public HashMap<String, Object> userLoginProcess(LoginDTO loginDto, HttpSession session, HttpServletRequest request, HttpServletResponse response) {
HashMap<String, Object> data = new HashMap<String, Object>();
UserVo sessionUser = userService.login(loginDto);
if (sessionUser != null) {
String state = sessionUser.getUser_status();
if (state.equals("Inactive")) {
data.put("result", "out");
} else if (!BCrypt.checkpw(loginDto.getUser_pw(), sessionUser.getUser_pw())) {
data.put("result", "fail");
} else {
data.put("result", "success");
session.setAttribute("sessionUser", sessionUser);
/* 아이디 저장 */
if (loginDto.isSaveCookie()) {
// 아이디 저장 유효기간 : 30일
int amount = 60 * 60 * 24 * 30;
// 아이디저장 쿠키 객체 생성
Cookie saveIdCooke = new Cookie("setCookieYN", "Y");
Cookie userInputId = new Cookie("userInputId", loginDto.getUser_id());
// 모든 경로에서 접근 가능하게 처리
saveIdCooke.setPath("/");
userInputId.setPath("/");
// 쿠키 유효 기간
saveIdCooke.setMaxAge(amount);
userInputId.setMaxAge(amount);
// 쿠키 저장
response.addCookie(saveIdCooke);
response.addCookie(userInputId);
} else {
Cookie saveCookie = WebUtils.getCookie(request, "setCookieYN");
Cookie userInputId = WebUtils.getCookie(request, "userInputId");
if (saveCookie != null && userInputId != null) {
saveCookie.setPath("/");
userInputId.setPath("/");
// 쿠키 유효기간 0
saveCookie.setMaxAge(0);
userInputId.setMaxAge(0);
// 쿠키 저장
response.addCookie(saveCookie);
response.addCookie(userInputId);
}
}
}
}
return data;
}
2.7 로그인 처리 화면 확인
'스프링 프레임워크 > 스프링 MVC' 카테고리의 다른 글
# Spring MVC 게시판 예제 10 : 내 프로필 페이지 구현하기 (0) | 2023.02.25 |
---|---|
# Spring MVC 게시판 예제 09 : 아이디 및 비밀번호 찾기 구현 (0) | 2023.02.24 |
# Spring MVC 게시판 예제 07 - 회원 가입 유효성 검사 (Feat. Validation) (0) | 2023.02.23 |
# Spring MVC 게시판 예제 06 - 회원가입 유효성 검사 (Feat. JavaScript) (0) | 2023.02.23 |
# Spring MVC 게시판 예제 05 - 회원가입 처리하기 (2) | 2023.02.22 |
댓글