감 잃지말고 개발하기

[JSP] [MVC] [JAVA] 이메일 전송으로 회원 비밀번호 변경 구현하기 #5. 서버 딴 구현(마지막) 본문

JSP/MVC

[JSP] [MVC] [JAVA] 이메일 전송으로 회원 비밀번호 변경 구현하기 #5. 서버 딴 구현(마지막)

persii 2023. 4. 25. 17:13

회원 관련 로직 중 회원이 비밀번호를 찾고 싶을 때 가입한 이메일로 인증코드를 발송하고, 인증코드를 가지고 회원 비밀번호를 변경하는 로직을 기록하고자 한다.

 

저번 포스팅에서는 3. 비밀번호 변경 페이지를 구현해 보았다.

이번 포스팅에서는 마지막 단계, 비밀번호 변경 페이지를 처리하는 4. 서버 딴 로직을 구현해 보도록 하겠다.

 


♠ 프로젝트 전체 로직 흐름이 궁금하면 아래 포스팅을 참고하세요 ♠

 

2023.04.25 - [JSP/MVC] - [JSP] [MVC] [JAVA] 이메일 전송으로 회원 비밀번호 변경 구현하기 #1. 구현 틀 잡기

 

[JSP] [MVC] [JAVA] 이메일 전송으로 회원 비밀번호 변경 구현하기 #1. 구현 틀 잡기

회원 관련 로직 중 비밀번호를 찾고 싶을 때 가입한 이메일로 인증코드를 발송하고, 인증코드를 가지고 회원 비밀번호를 변경하는 로직을 기록하고자 한다. 인증코드로 회원 비밀번호 변경하는

persimmon-ary-stepbystep.tistory.com


 

 

로직 흐름

  1. 브라우저에서 요청한 URL을 해당 컨트롤러가 받아 Action 클래스를 호출한다(MemberFrontController.java).
  2. Action 클래스에서 세션을 확인하고, 비즈니스 로직을 처리하는 클래스를 호출하여 비밀번호를 변경한다(MemberChangePwProAction.java). 페이지 이동 설정을 한다.
  3. Service 클래스에서 DAO클래스를 호출한다(MemberChangePwProService.java).
  4. DAO 클래스에서 MySQL8.0 DB에 접근해 데이터를 가져온다(MemberDAO).
  5. 페이지가 이동한다.

 

 

로직 흐름 코드 및 실행화면

1. 컨트롤러(MemberFrontController.java)

MemberFrontController 클래스에 아래 코드를 추가한다.

들어온 URL을 매핑하여 MemberChangePwProAction 클래스를 호출한다.

// 인증코드 이용, 새 비밀번호 변경 요청
else if (command.equals("/memberChangePwPro.me")) {
    action = new MemberChangePwProAction();
    try {
        forward = action.execute(req, resp);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

 

2. Action 클래스(MemberChangePwProAction.java)

해당 Action 클래스에서는 세션 속성을 확인하여

  1. 로그인 속성값이 없으면서
  2. 인증코드가 저장된 속성값이 있는 경우에만

비밀번호 변경 작업(DB 작업)이 이루어질 수 있도록 처리한다.

 

Action 클래스 로직 순서

  1. 브라우저에서 건너온 세션을 확인하여 로그인 상태에선 접근하지 못하도록 처리한다.
    • 로그인을 처리하는 클래스에서 사용자가 로그인을 하면 세션에 속성 "isLogin"에 true가 저장되도록 만들었기 때문에, 만약 이 isLogin 속성값이 null이 아니면 접근을 못하도록 해준다.
    • 이동하는 경로는 "/bookShopMain.ok" (홈 페이지)이다.
  2. 속성 "isLogin" 값이 null이라면(로그인이 안된 상태), 인증코드가 저장된 속성값을 가져온다. 
    • 속성값이 있는 경우, form에서 건너온 인증코드와 세션에 저장된 인증코드를 비교해 인증코드가 서로 동일한 경우에만 DB 작업이 이루어지도록 한다.
  3. Service 클래스를 호출해 비밀번호를 수정한다.
  4. DB 작업이 정상적으로 수행된 경우, 로그인 페이지로 이동하게 처리한다.
package action;

import java.io.PrintWriter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import svc.MemberChangePwProService;
import vo.ActionForward;

/** 인증코드를 받아 새 비밀번호로 변경하는 요청을 처리하는 Action 클래스 */
public class MemberChangePwProAction implements Action {

	@Override
	public ActionForward execute(HttpServletRequest req, HttpServletResponse resp) throws Exception {
		
		ActionForward forward = null;
		
		/* 브라우저에서 건너온 세션 확인 
		 * 로그인 상태에선 접근 못하게 설정 */
		HttpSession session = req.getSession(false);
		if(session != null) {
			// 세션이 생성되어 있는 경우
			if((String)session.getAttribute("isLogin") != null) {
				// 로그인된 상태
				session.invalidate();
				
				resp.setContentType("text/html;charset=utf-8");
				PrintWriter out = resp.getWriter();
				out.println("<script>");
				out.println("alert('접근 권한이 없습니다.');");
				out.println("location.href='/bookShopMain.ok';");
				out.println("</script>");
			} else if((String) session.getAttribute("authenticationCode") != null){
				// 비로그인 상태 & 인증코드를 받은 경우
				
				String authenCode = req.getParameter("authenCode");
				if(((String) session.getAttribute("authenticationCode")).equals(authenCode)) {
					// 세션에 저장된 인증코드와 <input>값으로 넘어온 인증코드가 일치하는 경우
					
					String m_id = req.getParameter("m_id");
					String newPw = req.getParameter("newPw");
					boolean updateResult = false;
					
					/* DB 작업 */
					MemberChangePwProService service = new MemberChangePwProService();
					updateResult = service.updatePw(m_id, newPw);
					if(updateResult) {
						// 수정 성공
						resp.setContentType("text/html;charset=utf-8");
						PrintWriter out = resp.getWriter();
						out.println("<script>");
						out.println("alert('정상적으로 수정되었습니다. 로그인 페이지로 돌아갑니다.');");
						out.println("location.href='/memberLogin.me';");
						out.println("</script>");
					} else {
						resp.setContentType("text/html;charset=utf-8");
						PrintWriter out = resp.getWriter();
						out.println("<script>");
						out.println("alert('비밀번호 수정에 실패했습니다.');");
						out.println("history.back(-1);");
						out.println("</script>");
					}
				} 
			} else {
				// 인증코드가 없는 경우
				resp.setContentType("text/html;charset=utf-8");
				PrintWriter out = resp.getWriter();
				out.println("<script>");
				out.println("alert('접근 권한이 없습니다.');");
				out.println("location.href='/bookShopMain.ok';");
				out.println("</script>");
			}
		} else {
			// 세션 생성 X 
			resp.setContentType("text/html;charset=utf-8");
			PrintWriter out = resp.getWriter();
			out.println("<script>");
			out.println("alert('접근 권한이 없습니다.');");
			out.println("location.href='/bookShopMain.ok';");
			out.println("</script>");
		}
		return forward;
	}

}

 

3. Service 클래스(MemberChangePwProService.java)

Service 클래스의 updatePw() 메서드는 인자로 들어온 아이디와 비밀번호를 가지고 회원정보를 수정한다.

package svc;

import static db.JdbcUtil.close;
import static db.JdbcUtil.commit;
import static db.JdbcUtil.getConnection;
import static db.JdbcUtil.rollback;

import java.sql.Connection;

import dao.MemberDAO;

/** 임시코드를 발급받은 후, 새 비밀번호로 변경하는 요청을 처리하는 비즈니스 클래스 */
public class MemberChangePwProService {

	/** 임시코드를 발급받은 후, 새 비밀번호로 변경하는 메서드 */
	public boolean updatePw(String m_id, String newPw) {

		int updateCount = 0;
		
		/* DB 작업 */
		Connection conn = getConnection();
		MemberDAO memberDAO = MemberDAO.getInstance();
		memberDAO.setConnection(conn);
		updateCount = memberDAO.updatePw(m_id, newPw);
		
		boolean updateResult = false;
		
		if(updateCount > 0) {
			commit(conn);
			updateResult = true;
		} else {
			rollback(conn);
		}
		close(conn);
		return updateResult;
	}
}

 

4. DAO 클래스(MemberDAO.java)

기존 MemberDAO 클래스에 아래 메서드를 추가해 준다.

/** 임시코드를 받은 후 회원 비밀번호를 수정하는 메서드 */
public int updatePw(String m_id, String newPw) {

    int updateCount = 0;
    String sql = "update jspbookshop.member "
               + "set m_pw=? "
               + "where m_id=?";

    try {
        pstmt = conn.prepareStatement(sql);
        pstmt.setString(1, newPw);
        pstmt.setString(2, m_id);
        updateCount = pstmt.executeUpdate();
    } catch (Exception e) {
        System.out.println(" updatePw(m_id, oldPw, newPw) ERROR : "+e);
    } finally {
        close(pstmt);
    }

    return updateCount;
}

 

5. 페이지 이동

모든 작업이 정상적으로 수행되면, alert창이 뜨고 로그인 페이지로 이동한다. 

 

 


 

 

이렇게 Java 이메일 라이브러리를 사용하여 비밀번호를 변경하는 로직이 모두 구현되었다.

 

 

이메일 전송으로 비밀번호 변경 구현 끝.