회원 가입 데이터 베이스 설계는 다음과 같이 하였다.
-- 데이터베이스 생성
CREATE DATABASE SIMPLEBLOG2 CHARACTER SET=UTF8;
-- 유저 생성
CREATE USER `SIMPLEBLOG2`@`LOCALHOST` IDENTIFIED BY '1111';
-- 권한 부여
GRANT ALL PRIVILEGES ON SIMPLEBLOG2.* TO `SIMPLEBLOG2`@`LOCALHOST`;
/**********************************/
/* Table Name: 회원 */
/**********************************/
CREATE TABLE users(
idx INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(45) UNIQUE NOT NULL COMMENT '아이디' ,
nickname VARCHAR(30) NULL COMMENT ' 닉네임',
password VARCHAR(100) NULL COMMENT '비밀번호',
email VARCHAR(50) NULL comment '이메일',
enabled INTEGER NOT NULL DEFAULT 1 COMMENT '계정사용여부',
upoint INT COMMENT '포인트',
regdate TIMESTAMP DEFAULT now()
);
CREATE TABLE user_roles (
user_role_id int(11) NOT NULL AUTO_INCREMENT,
username VARCHAR(45) UNIQUE NOT NULL COMMENT '아이디',
nickname VARCHAR(30) NULL COMMENT ' 닉네임',
role varchar(45) NOT NULL,
PRIMARY KEY (user_role_id),
UNIQUE KEY uni_username_role (role,username)
);
ALTER TABLE user_roles
ADD FOREIGN KEY (username) REFERENCES users(username);
/**********************************/
/* Table Name: 권한 */
/**********************************/
CREATE TABLE authorities(
username VARCHAR(45) NOT NULL COMMENT '회원아이디',
authority VARCHAR(20) NOT NULL COMMENT '권한'
);
ALTER TABLE authorities ADD CONSTRAINT IDX_authorities_FK0 FOREIGN KEY (username) REFERENCES users (username);
/**********************************/
/* Table Name: 그룹 */
/**********************************/
CREATE TABLE groups(
id VARCHAR(20) PRIMARY KEY NOT NULL COMMENT '그룹 아이디',
group_name VARCHAR(20) NULL COMMENT '그룹 명'
);
/**********************************/
/* Table Name: 그룹 권한 관계 */
/**********************************/
CREATE TABLE group_authorities(
group_id VARCHAR(20) NOT NULL COMMENT '그룹 아이디',
authority VARCHAR(20) NOT NULL COMMENT '권한'
);
ALTER TABLE group_authorities ADD CONSTRAINT IDX_group_authorities_FK0 FOREIGN KEY (group_id) REFERENCES groups (id);
/**********************************/
/* Table Name: 그룹 회원 관계 */
/**********************************/
CREATE TABLE group_members(
group_id VARCHAR(20) NOT NULL COMMENT '그룹 아이디',
username VARCHAR(45) NOT NULL COMMENT '회원 아이디'
);
ALTER TABLE group_members ADD CONSTRAINT IDX_group_members_FK0 FOREIGN KEY (username) REFERENCES users (username);
ALTER TABLE group_members ADD CONSTRAINT IDX_group_members_FK1 FOREIGN KEY (group_id) REFERENCES groups (id);
-- 회원 데이터 입력
INSERT INTO users (username, password, enabled) VALUES ('user', '1', 1);
INSERT INTO users (username, password, enabled) VALUES ('admin', '1', 1);
-- 회원 권한 입력
INSERT INTO authorities (username, authority) VALUES ('user', 'ROLE_USER');
INSERT INTO authorities (username, authority) VALUES ('admin', 'ROLE_ADMIN');
INSERT INTO authorities (username, authority) VALUES ('admin', 'ROLE_USER');
-- 그룹
INSERT INTO groups (id, group_name) VALUES ('G01', '관리자 그룹');
INSERT INTO groups (id, group_name) VALUES ('G02', '사용자 그룹');
-- 그룹 권한
INSERT INTO group_authorities (group_id, authority) VALUES ('G01', 'ROLE_ADMIN');
INSERT INTO group_authorities (group_id, authority) VALUES ('G01', 'ROLE_USER');
INSERT INTO group_authorities (group_id, authority) VALUES ('G02', 'ROLE_USER');
-- 그룹 회원
INSERT INTO group_members (group_id, username) VALUES ('G01', 'admin');
INSERT INTO group_members (group_id, username) VALUES ('G02', 'user');
ER 다이어 그램
이클립스 에서 ERMaster 를 설치하면 된다.
설치 방법 : [ERD TOOL] ECLIPSE ERMASTER PLUG-IN 설치
나비켓 프리미엄 모델링 이다.
만약 현재 블로그 포스팅이 이해가 안되면 이전에 포스팅한 주소를 참조 하기를 바란다.
1. 스프링 시큐리티 유효성 JSR-303 설정 방법 - 각종 @Pattern 정규식 유효성 체크 모음 스프링 설정 12 - CJH - 12 ★
2. 스프링 시큐리티 로그인 설정 13 - CJH - 13 ★
3. 스프링 시큐리티(Spring Security) 이용한 비밀번호 암호화 로그인 및 테스트 방법Bcrypt, Sha-256 등의 설정 15 - CJH - 15
pom.xml
시큐리티 의존성 라이브러리 설정
<!-- 시큐리티 최소 의존성 --> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-web</artifactId> <version>4.2.1.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-config</artifactId> <version>4.2.1.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-taglibs</artifactId> <version>4.2.1.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-core</artifactId> <version>4.2.1.RELEASE</version> </dependency>
security-context.xml
<intercept-url pattern="/member/**" access="permitAll" />
회원 가입 페이지 권한 설정이다.
<beans:bean id="bcryptPasswordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder" />
비밀번호 암호를 의존성 주입 한다.
<!-- 검사 URL -->
<http use-expressions="true">
<intercept-url pattern="/sample/**" access="permitAll"/>
<intercept-url pattern="/ajaxTest/**" access="permitAll"/>
<intercept-url pattern="/login/loginForm.do" access="permitAll"/>
<intercept-url pattern="/admin/**" access="hasRole('ADMIN')"/>
<intercept-url pattern="/login" access="hasRole('USER')" />
<intercept-url pattern="/" access="permitAll"/>
<intercept-url pattern="/user/**" access="hasAnyRole('USER, ADMIN')" />
<intercept-url pattern="/member/**" access="permitAll" />
<intercept-url pattern="/passwordEncoderTest" access="permitAll"/>
<form-login login-page="/login/loginForm.do"
default-target-url="/"
authentication-failure-url="/login/loginForm.do?error"
username-parameter="id"
password-parameter="password" />
<logout logout-url="/logout"
logout-success-url="/" />
<access-denied-handler error-page="/login/accessDenied.do"/>
<remember-me key="REMEMBER_ME_KEY"/>
</http>
<beans:bean id="bcryptPasswordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder" />
UsersVO
/**
* <pre>
* 1. 패키지명 : net.macaronics.web.domain
* 2. 타입명 : UsersVO.java
* 3. 작성일 : 2017. 12. 26. 오후 7:48:05
* 4. 저자 : 최준호
*
* </pre>
*
*/
package net.macaronics.join.domain;
import java.sql.Timestamp;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;
import org.hibernate.validator.constraints.NotBlank;
public class UsersVO {
private int idx; // 자동 증가
@NotBlank
@Size(min=4, max=30, message="아이디의 크기는 4에서 20 사이여야 합니다.")
@Pattern(regexp = ".*(?=.{4,})(?=.*[\\d[a-z][A-Z]]{4,}).*",
message = "최소 4 자리 / 알파벳 문자가 필요합니다.")
private String username; // 아이디 unique
@NotBlank(message="닉네임은 필수 입니다.")
@Pattern(regexp="^[ㄱ-ㅎ가-힣]*$", message="이름은 한글만 가능합니다.")
private String nickname; //닉네임
@NotNull(message="비밀번호는 필수 입니다.")
@Size(min=6, max=20, message="비밀번호는 6-20자 사이여야 합니다.")
@Pattern(regexp="([0-9].*[!,@,#,^,&,*,(,)])|([!,@,#,^,&,*,(,)].*[0-9])",
message="비밀번호는 숫자, 특수문자가 포함되어야 합니다.")
private String password; //패스워드
private String pwCheck;
@NotBlank(message="이메일은 필수 입니다.")
@Pattern(regexp="\\w+[@]\\w+\\.\\w+", message="이메일 형식에 맞지 않습니다.")
private String email; //이메일
private Integer enabled; // 계정사용여부
@NotBlank(message="포인트는 필수 입니다.")
@Pattern(regexp="^[0-9]*$", message="양수만 가능합니다.")
private String upoint; // 포인트
private Timestamp regdate; // 현재 날짜
public int getIdx() {
return idx;
}
public void setIdx(int idx) {
this.idx = idx;
}
//비밀번호 체크
public boolean passwordCheck() {
return password.equals(pwCheck);
}
~~setter, getter, toString()
생략
}
UsersJoinController
컨트롤
/**
* <pre>
* 1. 패키지명 : net.macaronics.web.controller
* 2. 타입명 : MemberJoinController.java
* 3. 작성일 : 2017. 12. 25. 오후 3:30:47
* 4. 저자 : 최준호
*
* </pre>
*
*/
package net.macaronics.join.controller;
import javax.validation.Valid;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import net.macaronics.join.domain.UsersVO;
import net.macaronics.join.service.UsersJoinService;
@Controller
@RequestMapping("/member/*")
public class UsersJoinController {
private static final Logger logger =LoggerFactory.getLogger(UsersJoinController.class);
private static final String ViewPage="memberJoin/joinForm";
@Autowired
private BCryptPasswordEncoder bCryptPasswordEncoder;
@Autowired
private UsersJoinService usersJoinService;
@RequestMapping(value="joinForm.do", method=RequestMethod.GET)
public String memberForm(UsersVO usersVO) throws Exception{
return ViewPage;
}
//bindResult 다음에 Model 이 와야 한다. 순서가 틀리면 에러가 발생한다.
@RequestMapping(value="join.do", method=RequestMethod.POST)
public String memberInsert(@ModelAttribute(name="usersVO") @Valid UsersVO usersVO, BindingResult bindResult, Model model ) throws Exception{
if(bindResult.hasErrors()) {
return ViewPage;
}
//username 중복 체크
if(usersJoinService.usersNameCheck(usersVO.getUsername())) {
// 0보다 크면 중복이 존재 true 반환
logger.info("중복된 아이디 입니다.");
model.addAttribute("idCheck", "중복된 아이디 입니다." );
return ViewPage;
}
//비밀번호 체크
if(!usersVO.passwordCheck()) {
logger.info("비밀번호와 비밀번호 확인이 일치하지 않습니다.");
model.addAttribute("pwCheck", "비밀번호와 비밀번호 확인이 일치하지 않습니다." );
return ViewPage;
}
//비밀번호 암오화 작업
if(StringUtils.hasText(usersVO.getPassword())) {
String bCryptString=bCryptPasswordEncoder.encode(usersVO.getPassword());
usersVO.setPassword(bCryptString);
}
usersJoinService.usersRegister(usersVO);
return "redirect:/";
}
}
DAO - @Repository
/**
* <pre>
* 1. 패키지명 : net.macaronics.join.persistence
* 2. 타입명 : UsersJoinDAOImpl.java
* 3. 작성일 : 2018. 1. 1. 오후 6:11:46
* 4. 저자 : 최준호
*
* </pre>
*
*/
package net.macaronics.join.persistence;
import org.apache.ibatis.session.SqlSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import net.macaronics.join.domain.UsersVO;
@Repository
public class UsersJoinDAOImpl implements UsersJoinDAO {
private static final String namespace = "net.macaronics.mapper.joinMapper.";
@Autowired
private SqlSession sqlSession;
public Integer usersNameCheck(String username) throws Exception {
return sqlSession.selectOne(namespace+"usersNameCheck", username);
}
//등록
@Override
public void usersRegister(UsersVO usersVO) {
sqlSession.insert(namespace+"usersRegister", usersVO);
}
}
joinMapper.xml
<?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와 중복되지 않도록 네임스페이스 기재 -->
<mapper namespace="net.macaronics.mapper.joinMapper">
<select id="usersNameCheck" resultType="int" >
select count(*) from USERS WHERE username =#{username}
</select>
<insert id="usersRegister" >
INSERT INTO USERS(username, nickname , password, email, upoint )
VALUES(#{username} , #{nickname} , #{password} , #{email} , 1)
</insert>
</mapper>
서비스
/**
* <pre>
* 1. 패키지명 : net.macaronics.join.service
* 2. 타입명 : UsersJoinServiceImpl.java
* 3. 작성일 : 2017. 12. 27. 오후 11:09:09
* 4. 저자 : 최준호
*
* </pre>
*
*/
package net.macaronics.join.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import net.macaronics.join.domain.UsersVO;
import net.macaronics.join.persistence.UsersJoinDAO;
@Service
public class UsersJoinServiceImpl implements UsersJoinService {
@Autowired
private UsersJoinDAO usersJoinDAO;
// usersname 중복 체크
@Override
public boolean usersNameCheck(String username) throws Exception {
boolean isCheck=false;
int check=usersJoinDAO.usersNameCheck(username);
// 0보다 크면 중복이 존재 true 반환
if(check>0) {
isCheck=true;
}else {
// 0이면 중복 없음.
isCheck=false;
}
return isCheck;
}
//등록
@Override
public void usersRegister(UsersVO usersVO) throws Exception {
usersJoinDAO.usersRegister(usersVO);
}
}
뷰 - joinForom.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- 위 3개의 메타 태그는 *반드시* head 태그의 처음에 와야합니다; 어떤 다른 콘텐츠들은 반드시 이 태그들 *다음에* 와야 합니다 -->
<title>회원 가입</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css">
<!-- 부가적인 테마 -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap-theme.min.css">
<!-- 합쳐지고 최소화된 최신 자바스크립트 -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js"></script>
<script src="//code.jquery.com/jquery.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<!-- IE8 에서 HTML5 요소와 미디어 쿼리를 위한 HTML5 shim 와 Respond.js -->
<!-- WARNING: Respond.js 는 당신이 file:// 을 통해 페이지를 볼 때는 동작하지 않습니다. -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->
</head>
<body>
<h1 class="text-center">회원 가입</h1>
<div class="row">
<div class="col-xs-3 col-sm-3"></div>
<div class="col-xs-6 col-sm-6">
'
<form:form method="post" commandName="usersVO" action="/member/join.do">
<table class="table">
<tr>
<td class="primary">아이디</td>
<td><form:input path="username" cssClass="form-control" /> <br>
<form:errors path="username" cssClass="label label-danger" /> <br>
<span class="label label-danger">${idCheck}</span>
</td>
</tr>
<tr>
<td class="primary">비밀번호</td>
<td><form:password path="password" cssClass="form-control" />
<br> <form:errors path="password" cssClass="label label-danger" />
</td>
</tr>
<tr>
<td class="primary">비밀번호확인</td>
<td><input type="password" name="pwCheck" class="form-control">
<br>
<span class="label label-danger">${pwCheck}</span></td>
</tr>
<tr>
<td class="primary">닉네임</td>
<td><form:input path="nickname" cssClass="form-control" /> <br>
<form:errors path="nickname" cssClass="label label-danger" /></td>
</tr>
<tr>
<td class="primary">이메일</td>
<td><form:input path="email" cssClass="form-control" /> <br>
<form:errors path="email" cssClass="label label-danger" />
</td>
</tr>
<tr>
<td class="primary">포인트</td>
<td><form:input path="upoint" cssClass="form-control" /> <br>
<form:errors path="upoint" cssClass="label label-danger" />
</td>
</tr>
<tr class="text-center">
<td colspan="2"><input type="submit" value="회원가입" class="btn btn-success">
</td>
</tr>
</table>
</form:form>
</div>
</div>
</body>
</html>
제작 : macaronics.net - Developer Jun Ho Choi
소스 : https://github.com/braverokmc79/spring_simple_blog/commits/master





















댓글 ( 5)
댓글 남기기