스프링

 

 

회원 가입 데이터 베이스 설계는 다음과 같이 하였다.

-- 데이터베이스 생성
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

 

 

 

 

 

spring

 

about author

PHRASE

Level 60  라이트

나의 허물을 보고 꾸짖어 주는 지자( 智者 )를 만나면 보배를 보여주는 사람을 보듯 대하여라. -성전

댓글 ( 5)

댓글 남기기

작성