일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
- RCPS
- Token
- MRC
- ui탬플릿
- 이미지 업로드
- 인증처리
- stock option
- 로그인
- 배포
- Update
- 밸류즈 홈페이지
- 달력 라이브러리
- 로그인 로직
- 공통메서드
- Ajax
- 빌드 및 배포
- react
- 마이페이지
- 회원가입로직
- jsonwebtoken
- 스프링시큐리티
- userManagement
- 캘린더 라이브러리
- mypage
- 관리자페이지
- 파생상품평가
- 밸류즈
- Typesciprt
- Styled Components
- register
- Today
- Total
I T H
[포트폴리오 프로젝트 4] 회원가입 페이지 구현 본문
사용자 로그인 페이지를 구현하기 전에 사용자로 등록할 수 있는 회원가입 페이지를 구현하고자 한다. 사용자 정보는 아이디 중복체크만 진행하여 받도록 처리한다.
스프링 시큐리티 설정을 완료한 상태로 가정하고 진행한다. 스프링 시큐리티는 연습용 프로젝트를 참고
[ 테이블 생성 ]
- 사용자 정보를 저장하기 위한 데이터베이스 테이블을 1개 생성한다.
CREATE TABLE `TBL_USER_INFO` (
`USER_ID` varchar(20) NOT NULL,
`USER_PWD` varchar(100) NOT NULL,
`USER_NAME` varchar(100) DEFAULT NULL,
`USER_AUTH` char(1) DEFAULT NULL,
`USER_TEL` varchar(20) DEFAULT NULL,
`USER_EMAIL` varchar(50) DEFAULT NULL,
`INPUT_DATETIME` datetime DEFAULT NULL,
PRIMARY KEY (`USER_ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
[ 프론트엔드 구성 - 회원가입 페이지 구현 ]
- 회원가입 페이지 JSP 를 구현하기 전
CSS, 메뉴 영역 등 공통으로 사용될 화면에 대한 파일을 따로 정리하여 둔다.
신규 화면이 구성될 때마다 include하여 사용하도록 하여 동일한 코드를 여러 번 반복하여 사용하지 않도록 하기 위함이다.
- 아래와 같이 inc 폴더 아래에 파일 구성을 해준다. (src\main\webapp\resources\inc)
ㄱ. footer.jsp
- 내용은 템플릿에 있는 내용 그대로 가져와서 붙여 넣는다. 추후 문구나 스타일은 변경하여 사용할 예정이다.
<!-- 하단 푸터와 간격을 조금 벌리기 위해 -->
<br/><br/>
<footer id="footer">
<div class="container">
<div class="row">
<div class="col-md-3 widget">
<h3 class="widget-title">Contact</h3>
<div class="widget-body">
<p>+234 23 9873237<br>
<a href="mailto:#">some.email@somewhere.com</a><br>
<br>
234 Hidden Pond Road, Ashland City, TN 37015
</p>
</div>
</div>
<div class="col-md-3 widget">
<h3 class="widget-title">Follow me</h3>
<div class="widget-body">
<p class="follow-me-icons">
<a href=""><i class="fa fa-twitter fa-2"></i></a>
<a href=""><i class="fa fa-dribbble fa-2"></i></a>
<a href=""><i class="fa fa-github fa-2"></i></a>
<a href=""><i class="fa fa-facebook fa-2"></i></a>
</p>
</div>
</div>
<div class="col-md-3 widget">
<h3 class="widget-title">Text widget</h3>
<div class="widget-body">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Atque, nihil natus explicabo ipsum quia iste aliquid repellat eveniet velit ipsa sunt libero sed aperiam id soluta officia asperiores adipisci maxime!</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Atque, nihil natus explicabo ipsum quia iste aliquid repellat eveniet velit ipsa sunt libero sed aperiam id soluta officia asperiores adipisci maxime!</p>
</div>
</div>
<div class="col-md-3 widget">
<h3 class="widget-title">Form widget</h3>
<div class="widget-body">
<p>+234 23 9873237<br>
<a href="mailto:#">some.email@somewhere.com</a><br>
<br>
234 Hidden Pond Road, Ashland City, TN 37015
</p>
</div>
</div>
</div> <!-- /row of widgets -->
</div>
</footer>
<footer id="underfooter">
<div class="container">
<div class="row">
<div class="col-md-6 widget">
<div class="widget-body">
<p>234 Hidden Pond Road, Ashland City, TN 37015 </p>
</div>
</div>
<div class="col-md-6 widget">
<div class="widget-body">
<p class="text-right">
Copyright © 2014, Your awesome name here<br>
Design: <a href="http://www.gettemplate.com" rel="designer">Initio by GetTemplate</a> </p>
</div>
</div>
</div> <!-- /row of widgets -->
</div>
</footer>
ㄴ. header.jsp
- css 파일들을 아래에 정리하여 준다.
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="">
<meta name="author" content="Sergey Pozhilov (GetTemplate.com)">
<title> TH's 포트폴리오 </title>
<link rel="shortcut icon" href="/resources/images/gt_favicon.png">
<!-- Bootstrap -->
<link href="http://netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.no-icons.min.css" rel="stylesheet">
<!-- Icons -->
<link href="http://netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css" rel="stylesheet">
<!-- Fonts -->
<link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Alice|Open+Sans:400,300,700">
<!-- Custom styles -->
<link rel="stylesheet" href="/resources/css/styles.css">
<!--[if lt IE 9]> <script src="/resources/js/html5shiv.js"></script> <![endif]-->
<link rel="stylesheet" href="/resources/lightslider/css/lightslider.css">
</head>
ㄷ. incJs.jsp
- javascript 파일들을 정리하여 준다. "/resources/js/util.js” 추가 -> javaConfig연습용에 있음.
<!-- JavaScript libs are placed at the end of the document so the pages load faster -->
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="http://netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"></script>
<script src="/resources/lightslider/js/lightslider.js"></script>
<script src="/resources/js/template.js"></script>
<script src="/resources/js/util.js"></script>
<script src="/resources/js/index.js"></script>
ㄹ. top.jsp
- 화면 상단의 메뉴 구성을 파일로 따로 분리하여 준다.
<header id="header">
<div id="head" class="parallax" parallax-speed="2">
<h1 id="logo" class="text-center">
<img id="profileImg" class="img-circle" src="/resources/images/profile/20230627165120.jpeg" alt="">
<span id="profileName" class="title">Anthony Russel</span>
<span id="profileJob" class="tagline">A mystery person</span>
<span class="tagline"><a id="profileEmail" href="">anthony.russel42@example.com</a></span>
</h1>
</div>
<nav class="navbar navbar-default navbar-sticky">
<div class="container-fluid">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button>
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li class="active"><a href="/">Home</a></li>
<li><a href="about.html">About</a></li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">More Pages <b class="caret"></b></a>
<ul class="dropdown-menu">
<li><a href="sidebar-left.html">Left Sidebar</a></li>
<li><a href="sidebar-right.html">Right Sidebar</a></li>
<li><a href="single.html">Blog Post</a></li>
</ul>
</li>
<li><a href="blog.html">Blog</a></li>
</ul>
</div><!--/.nav-collapse -->
</div>
</nav>
</header>
- Index.jsp 태그 추가
<%@include file="/resources/inc/top.jsp"%>
<%@include file="/resources/inc/incJs.jsp"%>
- 파일 정리 후 [ index.jsp ]
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html lang="kr">
<link rel="stylesheet" href="/resources/lightslider/css/lightslider.css">
<%@include file="/resources/inc/header.jsp"%>
<body class="home">
<%@include file="/resources/inc/top.jsp"%>
<main id="main">
<div class="container">
<div class="row section topspace">
<div class="col-md-12">
<p class="lead text-center text-muted">Let me tell you something my friend. hope is a dangerous thing. hope can drive a man insane. you <a href="about.html">measure</a> yourself by the people who measure themselves by you. it only took me <a href="sidebar-right.html">six days</a>. </p>
</div>
</div> <!-- / section -->
<div class="row section featured topspace">
<h2 class="section-title"><span>Services</span></h2>
<div class="row">
<div class="col-sm-6 col-md-3">
<h3 class="text-center">Custom website design</h3>
<p>I don't think they tried to market it to the billionaire, spelunking, base-jumping crowd. i did the same thing to gandhi, he didn't eat for three weeks. i once heard a wise man say there are no perfect men.</p>
<p class="text-center"><a href="" class="btn btn-action">Read more</a></p>
</div>
<div class="col-sm-6 col-md-3">
<h3 class="text-center">Wordpress integration</h3>
<p>I don't think they tried to market it to the billionaire, spelunking, base-jumping crowd. i did the same thing to gandhi, he didn't eat for three weeks. i once heard a wise man say there are no perfect men.</p>
<p class="text-center"><a href="" class="btn btn-action">Read more</a></p>
</div>
<div class="col-sm-6 col-md-3">
<h3 class="text-center">Application development</h3>
<p>I don't think they tried to market it to the billionaire, spelunking, base-jumping crowd. i did the same thing to gandhi, he didn't eat for three weeks. i once heard a wise man say there are no perfect men.</p>
<p class="text-center"><a href="" class="btn btn-action">Read more</a></p>
</div>
<div class="col-sm-6 col-md-3">
<h3 class="text-center">SEO & SEM services</h3>
<p>I don't think they tried to market it to the billionaire, spelunking, base-jumping crowd. i did the same thing to gandhi, he didn't eat for three weeks. i once heard a wise man say there are no perfect men.</p>
<p class="text-center"><a href="" class="btn btn-action">Read more</a></p>
</div>
</div>
</div> <!-- / section -->
<div class="row section recentworks topspace">
<h2 class="section-title"><span>Recent Works</span></h2>
<div class="thumbnails recentworks row">
<div class="col-xs-12 col-sm-6 col-md-4 col-lg-4">
<a class="thumbnail" href="sidebar-right.html">
<span class="img">
<img src="resources/images/s1.jpg" alt="">
<span class="cover"><span class="more">See details →</span></span>
</span>
<span class="title">Sample title - big data solutions</span>
</a>
<span class="details"><a href="">Web design</a> | <a href="">Wordpress</a> | <a href="">Logotype</a></span>
<h4></h4>
<p></p>
</div>
<div class="col-xs-12 col-sm-6 col-md-4 col-lg-4">
<a class="thumbnail" href="sidebar-right.html">
<span class="img">
<img src="resources/images/s1.jpg" alt="">
<span class="cover"><span class="more">See details →</span></span>
</span>
<span class="title">Pure ipsum - development services for people</span>
</a>
<span class="details"><a href="">Web design</a> | <a href="">Wordpress</a></span>
<h4></h4>
<p></p>
</div>
<div class="col-xs-12 col-sm-6 col-md-4 col-lg-4">
<a class="thumbnail" href="sidebar-right.html">
<span class="img">
<img src="resources/images/s1.jpg" alt="">
<span class="cover"><span class="more">See details →</span></span>
</span>
<span class="title">Lorem studios - interior and patio design</span>
</a>
<span class="details"><a href="">Web design</a> | <a href="">Logotype</a></span>
<h4></h4>
<p></p>
</div>
<div class="col-xs-12 col-sm-6 col-md-4 col-lg-4">
<a class="thumbnail" href="sidebar-right.html">
<span class="img">
<img src="resources/images/s1.jpg" alt="">
<span class="cover"><span class="more">See details →</span></span>
</span>
<span class="title">Pure ipsum - development services for people</span>
</a>
<span class="details"><a href="">Web design</a> | <a href="">Wordpress</a></span>
<h4></h4>
<p></p>
</div>
<div class="col-xs-12 col-sm-6 col-md-4 col-lg-4">
<a class="thumbnail" href="sidebar-right.html">
<span class="img">
<img src="resources/images/s1.jpg" alt="">
<span class="cover"><span class="more">See details →</span></span>
</span>
<span class="title">Lorem studios - interior and patio design</span>
</a>
<span class="details"><a href="">Web design</a> | <a href="">Logotype</a></span>
<h4></h4>
<p></p>
</div>
<div class="col-xs-12 col-sm-6 col-md-4 col-lg-4">
<a class="thumbnail" href="sidebar-right.html">
<span class="img">
<img src="resources/images/s1.jpg" alt="">
<span class="cover"><span class="more">See details →</span></span>
</span>
<span class="title">Lorem studios - interior and patio design</span>
</a>
<span class="details"><a href="">Web design</a> | <a href="">Logotype</a></span>
<h4></h4>
<p></p>
</div>
</div>
</div> <!-- /section -->
<div class="row section topspace">
<div class="panel panel-cta"><div class="panel-body">
<div class="col-lg-8">
<p>A simple, nice-looking <b>call to action box</b>. Boxing is about respect. getting it for yourself,
and taking it away from the other guy. no, this is mount everest. </p>
</div>
<div class="col-lg-4 text-right">
<a href="http://www.gettemplate.com/downloads/initio.zip " class="btn btn-primary btn-lg">Download template</a>
</div>
</div></div>
</div> <!-- /section -->
<div class="row section clients topspace">
<h2 class="section-title"><span>LANGUAGE</span></h2>
<ul id="lightSlider" class="gallery">
<li><img src="/resources/images/carousel/jquery.png" /></li>
<li><img src="/resources/images/carousel/java.png" /></li>
<li><img src="/resources/images/carousel/bootstrap.png" /></li>
<li><img src="/resources/images/carousel/spring.png" /></li>
<li><img src="/resources/images/carousel/react.jpg" /></li>
<li><img src="/resources/images/carousel/mysql.png" /></li>
<li><img src="/resources/images/carousel/oracle.png" /></li>
</ul>
</div> <!-- /section -->
<br/><br/>
</div> <!-- /container -->
</main>
<%@include file="/resources/inc/footer.jsp"%>
<%@include file="/resources/inc/incJs.jsp"%>
</body>
</html>
ㅁ. register.jsp (src\main\webapp\WEB-INF\views\register.jsp)
- 회원가입을 위한 정보를 입력 받을 페이지를 구현한다.
- 위에서 작성한 ㄱ~ㄹ 파일들을 페이지에 include하여 코드가 간결하게 보이도록 처리하는 것이 이번 장에 핵심이다.
- 추가로 해당 화면에서만 사용될 스크립트 파일을 따로 작성하여 include하여 사용하는 방식을 취한다.
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html lang="kr">
<%@include file="/resources/inc/header.jsp"%>
<style>
.row {
justify-content: center;
display: flex;
padding: 5px;
}
</style>
<body class="home">
<%@include file="/resources/inc/top.jsp"%>
<main id="main">
<div class="container">
<div class="section featured topspace">
<h2 class="section-title">
<span>회원 등록 페이지</span>
</h2>
<div class="row">
<div class="col-sm-6 col-md-6">
<h3 class="text-center">회원 등록 정보를 입력하세요.</h3>
<p>아이디를 비롯한 필수항목은 입력한 후 가입을 해야 정상 가입이 됩니다.</p>
</div>
</div>
<div style="" class="col-md-4 col-sm-4"></div> <!-- 빈 div 태그로 여백주기 -->
<div class="col-md-4 col-sm-4"
style="border: 1px solid #c5cfcb; border-radius: 5px; padding: 15px;">
<div class="row">
<div class="col-sm-12 col-md-12">
<label class="form-label" for="txtId">아이디 *</label> <input
type="text" id="txtId" class="form-control"> <br /> <a
id="btnDuplicate" class="btn w-btn-green button-hover">중복 체크</a>
</div>
</div>
<div class="row">
<div class="col-sm-12 col-md-12">
<label class="form-label" for="txtPassword">비밀번호 *</label> <input
type="password" id="txtPassword" class="form-control">
</div>
</div>
<div class="row">
<div class="col-sm-12 col-md-12">
<label class="form-label" for="txtPassword2">비밀번호 재입력 *</label> <input
type="password" id="txtPassword2" class="form-control">
</div>
</div>
<div class="row">
<div class="col-sm-12 col-md-12">
<label class="form-label" for="txtName">성명</label> <input
type="text" id="txtName" class="form-control">
</div>
</div>
<div class="row">
<div class="col-sm-12 col-md-12">
<label class="form-label" for="txtTel">전화번호</label> <input
type="text" id="txtTel" class="form-control">
</div>
</div>
<div class="row">
<div class="col-sm-12 col-md-12">
<label class="form-label" for="txtEmail">이메일</label> <input
type="text" id="txtEmail" class="form-control">
</div>
</div>
<br />
<div class="row">
<div class="text-center col-sm-12 col-md-12">
<a id="btnRegister" class="btn btn-block w-btn-green button-hover">회원등록</a>
</div>
</div>
</div>
</div>
<!-- / section -->
</div>
<!-- /container -->
</main>
<%@include file="/resources/inc/footer.jsp"%>
<%@include file="/resources/inc/incJs.jsp"%>
<!-- page script -->
<script src="/resources/views/register.js"></script>
</body>
</html>
- Dependency 추가
- 파일 업로드를 위한 라이브러리를 참조하기 위해 pom.xml 파일에 아래 내용을 추가한다.
참고 > https://commons.apache.org/proper/commons-fileupload/
FileUpload – Home
Commons FileUpload The Commons FileUpload package makes it easy to add robust, high-performance, file upload capability to your servlets and web applications. FileUpload parses HTTP requests which conform to RFC 1867, "Form-based File Upload in HTML". That
commons.apache.org
<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
ㅂ. register.js
- src\main\webapp\resources\views\register.js
- 스크립트에는 버튼 클릭 이벤트 및 컨트롤러 호출에 대한 ajax 코드를 담고 있으며,
해당 스크립트는 페이지가 로드된 시점에 자동으로 호출된다.
/*******************************************************************************
* register.js
* @author thevalue
* @since 2023
* @DESC 회원가입 화면 스크립트
******************************************************************************/
(function(){
function Register(){
//private variables
var dupliComplete = false; //아이디 중복 확인용 변수
//초기화 메서드
function _init(){
//이벤트 처리 함수 호출
bindEvent();
}
function bindEvent(){
// 가입 버튼 클릭 이벤트
$("#btnRegister").on("click", function() {
// validation check
var obj = validationCheck();
if(!obj){
return;
}
if(dupliComplete) {
cfSave("/register/saveAccountInfo.do", obj, function(data) {
if(data.success) {
alert("사용자 등록이 완료되었습니다. 로그인 페이지로 이동합니다.");
setTimeout(function() {
window.location.href = "/login";
}, 2000);
}
}, true, "POST");
}
if(obj && !dupliComplete) {
alert("사용자 계정 중복확인을 진행 후 시도하시기 바랍니다.");
return;
}
});
// duplicate 버튼 클릭 시 (아이디중복확인)
$("#btnDuplicate").on("click", function() {
var valid = true;
var txtId = $("#txtId").val();
if(txtId == "" || txtId == null) {
alert("아이디를 입력하시기 바랍니다.");
return;
}
if(valid) {
var obj = {
id : txtId
};
cfFind("/register/findUserId.do", obj, function(data) {
if(data.length > 0) {
alert("이미 사용중인 계정입니다.");
return;
} else {
alert("사용 가능한 아이디입니다.");
// 입력한 계정정보가 존재하지 않는 경우 체크 완료 표시
$("#btnDuplicate").attr("disabled", true);
$("#txtId").attr("disabled", true);
dupliComplete = true;
}
}, true, "POST");
}
});
}//bindEvent
/*
* 사용자 입력 폼 필수 값 등 validation check
* 일반적인 사용자 등록 시
*/
function validationCheck(){
var obj = {};
if($("#txtId").val() == null || $("#txtId").val() == "") {
alert("사용자 아이디를 입력하시기 바랍니다.");
$("#txtId").focus();
return false;
}
obj.userId = $("#txtId").val();
obj.userAuth = "1"; // 일반사용자 권한
if($("#txtName").val() == null || $("#txtName").val() == "") {
alert("사용자명을 입력하시기 바랍니다.");
$("#txtName").focus();
return false;
}
obj.userName = $("#txtName").val();
if($("#txtEmail").val() == null || $("#txtEmail").val() == "") {
alert("이메일을 입력하시기 바랍니다.");
$("#txtEmail").focus();
return false;
} else {
//이메일 형식 체크
/*var emailRegex = /^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;
var result = checkRegexp($("#txtEmail"),emailRegex);
if(!result){
alert("이메일 형식을 확인하세요.");
return false;
}*/
var reg_email = /^([0-9a-zA-Z_\.-]+)@([0-9a-zA-Z_-]+)(\.[0-9a-zA-Z_-]+){1,2}$/;
if(!reg_email.test($("#txtEmail").val())) {
alert("이메일 형식을 확인하세요.");
return false;
} }
obj.userEmail = $("#txtEmail").val();
var password1 = $("#txtPassword").val();
var password2 = $("#txtPassword2").val();
if(password1.length < 8) {
alert("비밀번호는 8자리 이상으로 설정하시기 바랍니다.");
return false;
}
if(password1 != password2) {
alert("비밀번호가 일치하지 않습니다.");
return false;
}
obj.userPwd = password1;
if($("#txtTel").val() == null || $("#txtTel").val() == "") {
alert("전화번호를 입력하시기 바랍니다.");
$("#txtTel").focus();
return false;
}
obj.userTel = $("#txtTel").val();
return obj;
}
function _finalize(){
}
return {
init : _init,
finalize: _finalize
}
}
var register = new Register();
register.init();
})();
[ 백앤드구성 ]
- ajax에서 컨트롤러 호출 후 데이터베이스까지 파라미터 전달할때 모델빈 사용
- 시큐리티 비밀번호 암호화기능 사용
[ domain 모델 빈 ]
- kr\co\values\login\domain\User.java
package kr.co.values.login.domain;
/*
* 사용자 테이블 컬럼 구조
* `USER_ID` varchar(20) NOT NULL,
`USER_PWD` varchar(100) NOT NULL,
`USER_NAME` varchar(100) DEFAULT NULL,
`USER_AUTH` char(1) DEFAULT NULL,
`USER_TEL` varchar(20) DEFAULT NULL,
`USER_EMAIL` varchar(50) DEFAULT NULL,
`INPUT_DATETIME` datetime DEFAULT NULL,
*/
public class User {
private String userId;
private String userPwd;
private String userName;
private String userAuth;
private String userTel;
private String userEmail;
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getUserPwd() {
return userPwd;
}
public void setUserPwd(String userPwd) {
this.userPwd = userPwd;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getUserAuth() {
return userAuth;
}
public void setUserAuth(String userAuth) {
this.userAuth = userAuth;
}
public String getUserTel() {
return userTel;
}
public void setUserTel(String userTel) {
this.userTel = userTel;
}
public String getUserEmail() {
return userEmail;
}
public void setUserEmail(String userEmail) {
this.userEmail = userEmail;
}
}
[ 컨트롤러 구현 ]
kr\co\values\register\web\RegisterController.java 파일을 생성하여 아래 내용을 입력한다.
package kr.co.values.register.web;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import kr.co.values.login.domain.User;
import kr.co.values.register.persistence.RegisterMapper;
import kr.co.values.register.service.RegisterService;
@Controller
public class RegisterController {
@Autowired
private RegisterMapper registerMapper;
@Autowired
private RegisterService registerService;
@RequestMapping("/register.do")
public String main() {
System.out.println("회원 가입 페이지로 이동");
return "register";
}
/**
* 사용자 아이디 중복 체크
* (/register/findUserId)
* @return
*/
@RequestMapping("/register/findUserId.do")
@ResponseBody
public List<Map<String, Object>> findUserId(@RequestBody Map<String, Object> param) {
List<Map<String, Object>> list = registerMapper.findUserId(param);
return list;
}
/**
* 사용자 신규 저장
* (/register/saveAccountInfo)
* @return
*/
@RequestMapping("/register/saveAccountInfo.do")
@ResponseBody
public Map<String, Object> saveAccountInfo(@RequestBody User user) {
Map<String, Object> result = new HashMap<String, Object>();
registerService.saveAccountInfo(user);
result.put("success", true);
return result;
}
}
[ 서비스 구현 ]
kr\co\values\register\service\RegisterService.java 파일을 생성한다.
package kr.co.values.register.service;
import kr.co.values.login.domain.User;
public interface RegisterService {
void saveAccountInfo(User map);
}
kr\co\values\register\service\RegisterServiceImpl.java 파일을 생성한다.
passwordEncoder 를 통해 비밀번호 암호화 로직이 포함되어 있다.
그 전에 시큐리티 패키지 설정을 먼저 하도록 함.
kr.co.values.security패키지를 만들고 SecurityConfig.java 파일을 작성한다.
package kr.co.values.security;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
/* Spring Security를 이용해 로그인/로그아웃/인증/인가 등을 처리하기 위한 설정 파일이다.
* @EnableWebSecurity가 붙어 있을 경우 Spring Security를 구성하는 기본적인 Bean들을 자동으로 구성해준다.
* WebSecurityConfigurerAdapter를 상속받으면 특정 메소드를 오버라이딩 함으로써 좀 더 손쉽게 설정할 수 있다.
*/
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter{
/*
* 주의) configure() 메소드는 파라미터 타입이 다른 동일한 메소드명이 존재하므로 확인 필수
* 인증 및 인가가 필요없는 url 을 지정하여 시큐리티 미적용되도록 처리한다.
* ex > /resources /css /img 등등
*/
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/webjars/**");
}
/* configure(HttpSecurity http) 메소드를 오버라이딩 한다는 것은 인증/인가에 대한 설정을 한다는 의미이다.
* 가장 중요한 메소드로 볼 수 있다.
*
* http.csrf().disable()는 csrf() 기능을 끄라는 설정이다.
* csrf는 보안 설정 중 post방식으로 값을 전송할 때 token을 사용해야하는 보안 설정이다.
* csrf은 기본으로 설정되어 있는데 사용시 보안성은 높아지지만
* 개발초기에는 불편함이 있다는 단점이 있어서 기능을 끈 것이다.
*/
/*
* 비밀번호 암호화를 위해 사용한다.
*/
@Bean
public PasswordEncoder encoder() {
return new BCryptPasswordEncoder();
}
}
[ RegisterServiceImpl.java ]
package kr.co.values.register.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import kr.co.values.login.domain.User;
import kr.co.values.register.persistence.RegisterMapper;
@Service
public class RegisterServiceImpl implements RegisterService {
@Autowired
private RegisterMapper registerMapper;
@Autowired
private PasswordEncoder passwordEncoder;
@Override
public void saveAccountInfo(User userInfo) {
String orgPassword = userInfo.getUserPwd();
String userId = userInfo.getUserId();
String decPassword = initUserPassword(orgPassword, userId);
userInfo.setUserPwd(decPassword);
registerMapper.saveAccountInfo(userInfo);
}
private String initUserPassword(String orgPassword, String userId) {
return passwordEncoder.encode(orgPassword);
}
}
[ 매퍼 구현 ]
kr\co\values\register\persistence\RegisterMapper.java 파일을 생성한다.
package kr.co.values.register.persistence;
import java.util.List;
import java.util.Map;
import kr.co.values.login.domain.User;
public interface RegisterMapper {
// 사용자 정보 조회
List<Map<String, Object>> findUserId(Map<String, Object> params);
// 사용자 등록
void saveAccountInfo(User params);
}
kr\co\values\register\persistence\RegisterMapper.xml 파일을 생성한다.
사용자 등록 쿼리에는 파라미터로 Map 형태가 아닌 모델빈을 통해 전달받도록 설정을 해보았다.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="kr.co.values.register.persistence.RegisterMapper">
<select id="findUserId" resultType="hashmap" parameterType="hashmap">
SELECT *
FROM TBL_USER_INFO
WHERE 1=1
AND USER_ID = #{id}
</select>
<insert id="saveAccountInfo" parameterType="kr.co.values.login.domain.User">
INSERT INTO TBL_USER_INFO (
USER_ID
, USER_PWD
, USER_NAME
, USER_AUTH
, USER_TEL
, USER_EMAIL
, INPUT_DATETIME
)
VALUES (
#{userId}
, #{userPwd}
, #{userName}
, #{userAuth}
, #{userTel}
, #{userEmail}
, NOW()
)
</insert>
</mapper>
- 모델 빈을 통해 파라미터로 받을 경우 변수명과 쿼리 매핑 시 컬럼을 일치시켜줘야 한다
[ 실행 결과 ]
- /register.do 로 접속 후 테스트
'Spring MyPortfolio Project' 카테고리의 다른 글
[포트폴리오 프로젝트 6] 관리자메뉴 - 사용자관리 페이지 구현 (0) | 2024.01.24 |
---|---|
[포트폴리오 프로젝트 5] 로그인 페이지 구현(spring security포함) (0) | 2024.01.24 |
[포트폴리오 프로젝트 3] 관리자 페이지 구현 - 프로필 업데이트 (2) | 2024.01.24 |
[포트폴리오 프로젝트 2] 메인페이지 구현 : 캐러셀 사용 (2) | 2024.01.24 |
[포트폴리오 프로젝트 1] 프로젝트 구현 - UI 템플릿 적용 (1) | 2024.01.24 |