MelonPeach

23. 스프링 회원가입 만들기 / 암호화 기능 추가

 

안녕하세요 MelonPeach입니다.

오늘은 암호화 기능에대해 포스팅하겠습니다.

사용자의 개인정보를 특수문자, 영어 숫자등으로 암호화를 하여 데이터베이스에

저장을 하게되면 개인정보의 피해를 막을수 있겠지요.

 

 

1. pom.xml 작성


스프링 회원가입 만들기 / 암호화 기능(pom.xml)

 

스프링 시큐리티를 pom.xml에 적용시킵니다.(core, web, config)

 

      <!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-core -->
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-core</artifactId>
    <version>5.0.8.RELEASE</version>
</dependency>

		
<!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-web -->
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-web</artifactId>
    <version>5.0.8.RELEASE</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-config -->
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-config</artifactId>
    <version>5.0.8.RELEASE</version>
</dependency>

 

 

 

2. spring-security.xml 작성


스프링 회원가입 만들기 / 암호화 기능(spring-security.xml)

 

src -> main -> webapp -> WEB-INF -> spring 경로에

spring-security.xml파일을 하나 만들고 코드를 추가해줍니다.

 

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
    xmlns:beans="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/security
    http://www.springframework.org/schema/security/spring-security.xsd">
      
    <beans:bean id="bcryptPasswordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder" /> 
</beans:beans>

 

 

 

3. web.xml 작성


스프링 회원가입 만들기 / 암호화 기능(web.xml)

 

spring-security.xml을 읽을수 있게 설정해줍니다.

 

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

	<!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>/WEB-INF/spring/root-context.xml</param-value>
	</context-param>
	
	<!-- Creates the Spring Container shared by all Servlets and Filters -->
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>

	<!-- Processes application requests -->
	<servlet>
		<servlet-name>appServlet</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>
				/WEB-INF/spring/appServlet/servlet-context.xml
				/WEB-INF/spring/spring-security.xml
			</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
		
	<servlet-mapping>
		<servlet-name>appServlet</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>

	<!-- 한글 인코딩 Start -->
	<filter>
		<filter-name>encodingFilter</filter-name>
		<filter-class>
			org.springframework.web.filter.CharacterEncodingFilter
		</filter-class>
		<init-param>
			<param-name>encoding</param-name>
			<param-value>UTF-8</param-value>
		</init-param>
		<init-param>
			<param-name>forceEncoding</param-name>
			<param-value>true</param-value>
		</init-param>
	</filter>
	<filter-mapping>
		<filter-name>encodingFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>
	<!-- 한글 인코딩 End -->
</web-app>

 

 

 

4. MemberController.java 작성


스프링 회원가입 만들기 / 암호화 기능(MemberController.java)

 

암호화 기능을 사용할수 있게 BCryptPasswordEncoder를 추가해줍니다.

 

스프링 회원가입 만들기 / 암호화 기능(MemberController.java)

 

회원가입 요청이 들어오면 비밀번호를 암호화하여 vo에 다시 넣어줍니다. 그리고 회원가입 서비스를 실행합니다.

 

스프링 회원가입 만들기 / 암호화 기능(MemberController.java)

 

회원가입을 암호화를 하여 했기때문에 로그인을 할 때에는 입력된 비밀번호와 조회한 비밀번호가 맞아야하는데요.

먼저 비밀번호를 조회해야겠지요. service.login서비스를 실행하여 login.getUserPass를 가저올 수 있도록합니다.

pwdEncoder.matches(입력된 비밀번호(), 암호화된 비밀번호()) 비교를 해줍니다. 맞으면 true 틀리면 false를 반환하여 로그인을 진행합니다.

 

스프링 회원가입 만들기 / 암호화 기능(MemberController.java)

 

회원정보 수정은 memberUpdateView.jsp 에서 ajax를 이용하여 passChk() 요청을 해주기 때문에 간단한 서비스만 실행해줍니다. 수정을 완료하면 세션을 끊어줍니다.

 

스프링 회원가입 만들기 / 암호화 기능(MemberController.java)

 

회원탈퇴도 회원수정과 동일하게 passChk()요청에서 비밀번호를 비교해주기때문에 서비스만 실행시켜줍니다.

 

package kr.co.controller;


import javax.inject.Inject;
import javax.servlet.http.HttpSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import kr.co.service.MemberService;
import kr.co.vo.MemberVO;

@Controller
@RequestMapping("/member/*")
public class MemberController {

	private static final Logger logger = LoggerFactory.getLogger(MemberController.class);
	
	@Inject
	MemberService service;
	
	@Inject
	BCryptPasswordEncoder pwdEncoder;
	
	// 회원가입 get
	@RequestMapping(value = "/register", method = RequestMethod.GET)
	public void getRegister() throws Exception {
		logger.info("get register");
	}
	
	// 회원가입 post
	@RequestMapping(value = "/register", method = RequestMethod.POST)
	public String postRegister(MemberVO vo) throws Exception {
		logger.info("post register");
		int result = service.idChk(vo);
		try {
			if(result == 1) {
				return "/member/register";
			}else if(result == 0) {
				String inputPass = vo.getUserPass();
				String pwd = pwdEncoder.encode(inputPass);
				vo.setUserPass(pwd);
				
				service.register(vo);
			}
			// 요기에서~ 입력된 아이디가 존재한다면 -> 다시 회원가입 페이지로 돌아가기 
			// 존재하지 않는다면 -> register
		} catch (Exception e) {
			throw new RuntimeException();
		}
		return "redirect:/";
	}
	
	// 로그인 post
	@RequestMapping(value = "/login", method = RequestMethod.POST)
	public String login(MemberVO vo, HttpSession session, RedirectAttributes rttr) throws Exception{
		logger.info("post login");
	
		session.getAttribute("member");
		MemberVO login = service.login(vo);
		boolean pwdMatch = pwdEncoder.matches(vo.getUserPass(), login.getUserPass());

		if(login != null && pwdMatch == true) {
			session.setAttribute("member", login);
		} else {
			session.setAttribute("member", null);
			rttr.addFlashAttribute("msg", false);
		}
		
		
		return "redirect:/";
	}
	
	// 로그아웃 post
	@RequestMapping(value = "/logout", method = RequestMethod.GET)
	public String logout(HttpSession session) throws Exception{
		
		session.invalidate();
		
		return "redirect:/";
	}
	
	// 회원정보 수정 get
	@RequestMapping(value="/memberUpdateView", method = RequestMethod.GET)
	public String registerUpdateView() throws Exception{
		return "member/memberUpdateView";
	}
	
	// 회원정보 수정  post
	@RequestMapping(value="/memberUpdate", method = RequestMethod.POST)
	public String registerUpdate(MemberVO vo, HttpSession session) throws Exception{
		
/*		MemberVO login = service.login(vo);
		
		boolean pwdMatch = pwdEncoder.matches(vo.getUserPass(), login.getUserPass());
		if(pwdMatch) {
			service.memberUpdate(vo);
			session.invalidate();
		}else {
			return "member/memberUpdateView";
		}*/
		service.memberUpdate(vo);
		session.invalidate();
		return "redirect:/";
	}
	
	// 회원 탈퇴 get
	@RequestMapping(value="/memberDeleteView", method = RequestMethod.GET)
	public String memberDeleteView() throws Exception{
		return "member/memberDeleteView";
	}
	
	// 회원 탈퇴 post
	@RequestMapping(value="/memberDelete", method = RequestMethod.POST)
	public String memberDelete(MemberVO vo, HttpSession session, RedirectAttributes rttr) throws Exception{
		
		service.memberDelete(vo);
		session.invalidate();
		
		return "redirect:/";
	}
	
	// 패스워드 체크
	@ResponseBody
	@RequestMapping(value="/passChk", method = RequestMethod.POST)
	public boolean passChk(MemberVO vo) throws Exception {

		MemberVO login = service.login(vo);
		boolean pwdChk = pwdEncoder.matches(vo.getUserPass(), login.getUserPass());
		return pwdChk;
	}
	
	// 아이디 중복 체크
	@ResponseBody
	@RequestMapping(value="/idChk", method = RequestMethod.POST)
	public int idChk(MemberVO vo) throws Exception {
		int result = service.idChk(vo);
		return result;
	}
}



 

5. memberUpdateView.jsp 작성


스프링 회원가입 만들기 / 암호화 기능(memberUpdateView.jsp)

 

ajax를 이용하여 passChk로 요청을 보내고 passChk에서의 return값을 success: function(data) 파라미터로 넘겨줍니다.

data가 true면 회원수정. 아니면 비밀번호가 틀렸다는 메세지를 보여줍니다.

 

스프링 회원가입 만들기 / 암호화 기능(memberUpdateView.jsp)

 

form태그에 아이디를 넣어줍니다(form id="updateForm")그리고 안에 있던 버튼을 밖으로 꺼내주고 type을 button으로 수정해줍니다.

 

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<html>
	<head>
		<!-- 합쳐지고 최소화된 최신 CSS -->
		<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="//cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
		<title>회원가입</title>
	</head>
	<script type="text/javascript">
		$(document).ready(function(){
			// 취소
			$(".cencle").on("click", function(){
				
				location.href = "/";
						    
			})
		
			$("#submit").on("click", function(){
				if($("#userPass").val()==""){
					alert("비밀번호를 입력해주세요.");
					$("#userPass").focus();
					return false;
				}
				if($("#userName").val()==""){
					alert("성명을 입력해주세요.");
					$("#userName").focus();
					return false;
				}
				$.ajax({
					url : "/member/passChk",
					type : "POST",
					dateType : "json",
					data : $("#updateForm").serializeArray(),
					success: function(data){
						
						if(data==true){
							if(confirm("회원수정하시겠습니까?")){
								$("#updateForm").submit();
							}
							
						}else{
							alert("패스워드가 틀렸습니다.");
							return;
							
						}
					}
				})
			});
		})
	</script>
	<body>
		<section id="container">
			<form id="updateForm" action="/member/memberUpdate" method="post">
				<div class="form-group has-feedback">
					<label class="control-label" for="userId">아이디</label>
					<input class="form-control" type="text" id="userId" name="userId" value="${member.userId}" readonly="readonly"/>
				</div>
				<div class="form-group has-feedback">
					<label class="control-label" for="userPass">패스워드</label>
					<input class="form-control" type="password" id="userPass" name="userPass" />
				</div>
				<div class="form-group has-feedback">
					<label class="control-label" for="userName">성명</label>
					<input class="form-control" type="text" id="userName" name="userName" value="${member.userName}"/>
				</div>
			</form>
				<div class="form-group has-feedback">
					<button class="btn btn-success" type="button" id="submit">회원정보수정</button>
					<button class="cencle btn btn-danger" type="button">취소</button>
				</div>
		</section>
		
	</body>
	
</html>

 

 

 

6. memberDeleteView.jsp 작성


스프링 회원가입 만들기 / 암호화 기능(memberDeleteView.jsp)

 

회원탈퇴도 회원수정과 같은 방식입니다.

 

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<html>
	<head>
		<!-- 합쳐지고 최소화된 최신 CSS -->
		<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="//cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
		<title>회원탈퇴</title>
	</head>
	<script type="text/javascript">
		$(document).ready(function(){
			// 취소
			$(".cencle").on("click", function(){
				
				location.href = "/";
						    
			})
		
			$("#submit").on("click", function(){
				if($("#userPass").val()==""){
					alert("비밀번호를 입력해주세요.");
					$("#userPass").focus();
					return false;
				}
				$.ajax({
					url : "/member/passChk",
					type : "POST",
					dateType : "json",
					data : $("#delForm").serializeArray(),
					success: function(data){
						
						if(data==true){
							if(confirm("회원탈퇴하시겠습니까?")){
								$("#delForm").submit();
							}
						}else{
							alert("패스워드가 틀렸습니다.");
							return;
						}
					}
				})
				
			});
			
				
			
		})
	</script>
	<body>
		<section id="container">
			<form action="/member/memberDelete" method="post" id="delForm">
				<div class="form-group has-feedback">
					<label class="control-label" for="userId">아이디</label>
					<input class="form-control" type="text" id="userId" name="userId" value="${member.userId}" readonly="readonly"/>
				</div>
				<div class="form-group has-feedback">
					<label class="control-label" for="userPass">패스워드</label>
					<input class="form-control" type="password" id="userPass" name="userPass" />
				</div>
				<div class="form-group has-feedback">
					<label class="control-label" for="userName">성명</label>
					<input class="form-control" type="text" id="userName" name="userName" value="${member.userName}" readonly="readonly"/>
				</div>
			</form>
			<div class="form-group has-feedback">
				<button class="btn btn-success" type="button" id="submit">회원탈퇴</button>
				<button class="cencle btn btn-danger" type="button">취소</button>
			</div>
			<div>
				<c:if test="${msg == false}">
					비밀번호가 맞지 않습니다.
				</c:if>
			</div>
		</section>
		
	</body>
	
</html>

 

 

 

7. memberMapper.xml 작성


스프링 회원가입 만들기 / 암호화 기능(memberMapper.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 namespace="memberMapper">
	<!-- 회원가입 -->
	<insert id="register">
	    INSERT INTO MP_MEMBER(   USERID 
	   					       , USERPASS 
	   					       , USERNAME 	)
	                  VALUES(    #{userId} 
	                 		   , #{userPass}
	                 		   , #{userName})
   
    </insert>
    
    <!-- 로그인 -->
	<select id="login" resultType="kr.co.vo.MemberVO">
		SELECT USERID, USERPASS, USERNAME
		  FROM MP_MEMBER
		 WHERE USERID = #{userId}
		 <!--  AND USERPASS = #{userPass} -->
	</select>
	
	
	<!-- 회원정보 수정 -->
	<update id="memberUpdate">
		UPDATE MP_MEMBER SET 
		<!-- USERPASS = #{userPass}, -->
		USERNAME = #{userName}
		WHERE USERID = #{userId}
	</update>
	
	<!-- 회원탈퇴 -->
	<delete id="memberDelete">
		DELETE FROM MP_MEMBER
		WHERE USERID = #{userId}
		 <!--  AND USERPASS = #{userPass} --> 
	</delete>
	
	<!-- 패스워드 체크 -->
	<select id="passChk" resultType="int">
		SELECT COUNT(*) FROM MP_MEMBER
		WHERE USERID = #{userId}
		  AND USERPASS = #{userPass}
	</select>
	
		<!-- 아이디 중복 체크 -->
	<select id="idChk" resultType="int">
		SELECT COUNT(*) FROM MP_MEMBER
		WHERE USERID = #{userId}
	</select>
</mapper>

 

 

 

8. 실행 테스트


스프링 회원가입 만들기 / 암호화 기능(실행테스트)


 

회원가입을 하고 데이터를 조회해보면 암호화가된 상태를 보실수 있습니다.

 

압축파일도 같이 첨부합니다. 7z프로그램을 이용하여 푸셔야해요.

 

study.7z.001
6.00MB
study.7z.002
6.00MB
study.7z.003
3.67MB

 

이 글을 공유합시다

facebook twitter googleplus kakaostory naver