티스토리 뷰


스프링으로 비밀번호 찾기 기능을 구현해 보겠습니다.


우선 해야할일이 3가지 있습니다.

1.이메일이 형식에 맞춰서 잘 입력 됬는지 확인하는 일

2.이메일이 실제 데이터베이스에 저장되어있는지

3.실제로 저장되어있는 이메일이라면 그 이메일로 아이디와 비밀번호를 전송하는 일


1번부터 차근차근 알아 보도록 하겠습니다.


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
31
32
33
<form:form id="signupform" class="form-horizontal" role="form" commandName = "userDto" action="find_pass" method="post">
                                <div class="form-group">
                                    <label for="email" class="col-md-2 control-label">이메일</label>
                                    <div class="col-md-10">
                                        <input type="text" class="form-control" name="bEmail" value="${userDto.bEmail}"placeholder="이메일을 작성해주세요">
                                    </div>
                                    
                                        <div class="col-md-offset-2 col-md-10">
                                            <div style="color:red ; margin-top:2px" >
                                                <form:errors path="bEmail"/>
                                                 <form:errors/>
                                            </div>
                                        </div>                 
                                    
                                </div>
                                    
                                <div class="form-group" style="margin-left:82%">
                                    <!-- Button -->
                                                  
                                    <div class="col-md-offset-10 col-md-9">
                                        <button id="btn-signup" type="submit" class="btn btn-warning">확인</button>
                                    </div>
                                </div>
                                
                                <div class="form-group">
                                    <div class="col-md-12 control">
                                        <div style="border-top: 1px solid#888; padding-top:15px; font-size:85%" >
                                                가입하신 이메일로 아이디와 비밀번호를 전송해드리겠습니다.
                                        </div>
                                    </div>
                                </div>    
                                
                            </form:form>
cs


find_passView.jsp 에서 필요한 부분만 인용했습니다.

<form:form id="signupform" commandName = "userDto" action="find_pass" method="post">

<input type="text" class="form-control" name="bEmail" value="${userDto.bEmail}"placeholder="이메일을 작성해주세요">


비밀번호 찾기 화면에서 적절한 값을 입력하고 확인 버튼을 누르게 되면 userDto라는 커맨드 객체의 필드의 bEmail에 input태그에 입력한 값이 

들어가게 됩니다.

(form태그를 사용하려면 

<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> jsp파일 맨위에 이것을 추가해줘야 합니다.)


UserContoller.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@RequestMapping(value="/find_pass", method = RequestMethod.POST)
    public String find_pass(UserDto userDto,RedirectAttributes redirectattr,Errors errors) {
        new FindPassValidator().validate(userDto, errors);
        if(errors.hasErrors())
            return "find_passView";
        
        FindpassService service = new FindpassService();
        
        try {
            UserDto resultDto = service.execute(sqlsession, userDto);
            redirectattr.addFlashAttribute("resultDto",resultDto); 
            return "redirect:sendpass";
        }catch(Exception e)
        {
            errors.reject("EmailNotExist");
            return "find_passView"
        }
        
    }
cs


컨트롤러 클래스에서 /find_pass 요청을 받아들입니다. 

(method를 post로 지정하면 이 컨트롤러 메소드는 post방식의 요청만 받아들이고 method를 따로 지정하지 않으면 get,post둘다 받아들일수 있습니다.)


우선 1차적으로 FindPassValidator 라는 클래스의 validate함수로 1차적으로 이메일이 제대로된 형식으로 입력 됬는지 검증하고있습니다.


그리고 나서 그 검증과정에서 오류가 하나라도 있었으면 다시 비밀번호 찾기 화면으로 돌아가게 됩니다.


1차검증을 통과하게 된다면 서비스 객체로 제어를 넘깁니다. 


userDto는 뷰에서 사용자가 입력한 데이터가 들어있는데, 이 데이터를 통해서 값을 꺼내오고 꺼내온 값이 제대로된 값인지 확인을 하는 일을

FindpassService객체가 해줍니다.


그리고나서 비밀번호 전송하는 역할을 해주는 컨트롤러로 제어를 다시 넘깁니다. 


이때 컨트롤러 -> 컨트롤러로 제어를 넘기기 위해서 redirect를 사용했는데 

리다이렉트를 사용하면 모델에 있는 값이 초기화 되기때문에 매개변수로 RedirectAttributes redirectattr를 사용했습니다

이것을 써주게 되면 리다이렉트 시에도 redirectattr.addFlashAttribute("resultDto",resultDto);

이런식으로 커맨드 객체를 같이 넘겨줄수있게됩니다.(받는 컨트롤러 에서는 모델로 받아야 합니다)



만약 사용자가 입력한 아이디와 이메일이 일치하지 않거나 아이디가 존재하지 않는다면 findpass 서비스 객체는 예외를 컨트롤러로 던지게 되고,

컨트롤러는 적절한 에러코드를 errors.reject("EmailNotExist"); 설정하고 제어를 다시 비밀번호 찾기 화면으로 넘기게 됩니다.


다시 비밀번호 찾기 화면으로 돌아갔을때는 에러코드가 설정되어있으므로 적절한 에러메세지를 출력할수 있겠죠?


(에러코드 사용법 모르시면 제 블로그 에러코드 사용법 글 참고)

                       


FindPassValidator


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
public class FindPassValidator implements Validator { //비밀번호 찾기 화면에서 이메일과 아이디가 제대로 입력 됬는지 검증하는 클래스
 
    private Pattern pattern;
    private Matcher matcher;
    String regexp = "^[_a-z0-9-]+(.[_a-z0-9-]+)*@(?:\\w+\\.)+\\w+$"//이메일 정규 표현식
    public FindPassValidator() {
        pattern = pattern.compile(regexp);
    }
    @Override
    public boolean supports(Class<?> clazz) {
        return UserDto.class.isAssignableFrom(clazz);
    }
 
    @Override
    public void validate(Object target, Errors errors) {
        UserDto userDto = (UserDto)target;    
        //이메일이 올바른 형식인지 검사
        matcher = pattern.matcher(userDto.getbEmail());
        if(userDto.getbEmail() == null || userDto.getbEmail().trim().isEmpty())
            errors.rejectValue("bEmail""EmailRequired");
        else if(!matcher.matches()) //사용자가 입력한 이메일이 정규표현식에 매치 되지않는다면
            errors.rejectValue("bEmail""bad");
            
        
    }
 
}
cs


커스터마이징한 validator를 구현하고 싶으면 우선 validator라는 인터페이스를 구현한 클래스를 만들어야 합니다.

그렇게 하면 자동으로 validate라는 함수를 오버라이드 하게 되는데 우리는 이것을 구현해주면 됩니다.


우선 이 validate라는 함수는 검증을 시작할 객체인 target과 그 객체에 설정할 에러코드를 위한 errors객체 2개를 인자로 받게 됩니다.


우선, 사용자가 입력한 이메일이 비어있거나 공백으로만 입력이 되있으면 errors.rejectValue("bEmail""EmailRequired"); 처럼 userDto의 bEmail필드에

EmailRequired 라는 에러 코드를 설정하게 되고 그렇게 되면 label.properties파일에있는 EmailRequired = 이메일을 입력해주세요 구문을 통해서

적절한 에러메세지가 뷰에서 출력되게 됩니다.


또한 사용자가 입력한 이메일이 이메일 정규 표현식에 맞는지 확인하고, 마찬가지로 에러코드를 설정해줍니다.

이것이 1차 검증입니다.


FindpassService



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class FindpassService {
    
    public UserDto execute(SqlSession sqlsession ,UserDto userDto) throws Exception {
            
            UserDao dao = sqlsession.getMapper(UserDao.class);
            UserDto resultdto = dao.find_by_Email(userDto);
            if(resultdto == null)
                throw new Exception();
            //사용자가 입력한 아이디가 존재하지 않으면 예외 던짐.
            return resultdto;
        
    }
 
 
}
cs



이 서비스 객체에서는 mybatis를 활용해서 데이터를 꺼내오고 꺼내온 결과를 resultDto 커맨드 객체에 담으며 그 커맨드 객체가 없을경우 (이메일로 인한 쿼리문 실패)

(select * from userinfo where bEmail = 사용자가입력한이메일) 예외를 발생시키고

정상적일 경우 꺼내온 값을 리턴시키고있습니다.


mybatis사용에 익숙하지 않으신분은 제 블로그 mybatis편을 참고하시기 바랍니다.


예외가 발생하면 컨트롤러에서 EmailNotExist라는 에러코드를 커맨드 객체에 설정하게 됩니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<form:form id="signupform" class="form-horizontal" role="form" commandName = "userDto" action="find_pass" method="post">
                                <div class="form-group">
                                    <label for="email" class="col-md-2 control-label">이메일</label>
                                    <div class="col-md-10">
                                        <input type="text" class="form-control" name="bEmail" value="${userDto.bEmail}"placeholder="이메일을 작성해주세요">
                                    </div>
                                    
                                        <div class="col-md-offset-2 col-md-10">
                                            <div style="color:red ; margin-top:2px" >
                                                <form:errors path="bEmail"/>
                                                 <form:errors/>
                                            </div>
                                        </div>                 
                                    
                                </div>
cs


그렇게 되면 위 처럼 find_passView.jsp에서 적절한 에러코드를 출력할수 있게 됩니다.

<form:errors/> -> 커맨드 객체에 설정돼있는 에러코드 출력 -> 컨트롤러에서 설정됨.

<form:errors path="bEmail"/> -> 커맨드 객체 (userDto)의 bEmail필드에 설정돼있는 에러코드 출력 -> 1차검증시 validator에서 설정됨.



만약 1,2차 검증을 통과했다면

이제 사용자에게 아이디와 비밀번호를 보내줘야 합니다.


우선 자바 메일을 사용하기 위해서 폼파일에 아래 내용을 추가 해줍니다.


1
2
3
4
5
6
<!-- Java Mail API -->
          <dependency>
             <groupId>javax.mail</groupId>
             <artifactId>mail</artifactId>
             <version>1.4.7</version>
          </dependency>
cs



그리고나서

root-context.xml에

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!-- 메일 보내기 -->
    <bean id="mailSender" class = "org.springframework.mail.javamail.JavaMailSenderImpl">
      <property name="host" value="smtp.gmail.com" />
      <property name="port" value="587" />
      <property name="username" value="springteam11@gmail.com" />
      <property name="password" value="springteam!!" />
      <property name="javaMailProperties">
            <props>
             <prop key="mail.transport.protocol">smtp</prop>
             <prop key="mail.smtp.auth">true</prop>
             <prop key="mail.smtp.starttls.enable">true</prop>
             <prop key="mail.debug">true</prop>
            </props>
        </property>
   </bean>
cs

아래 내용을 추가해줍니다. 자바에서 메일 보내는 기능을 사용하기 위해 mailSender를 빈으로 등록해주는 과정입니다.


그리고나서, 실제로 메일을 보내줄 컨트롤러를 하나 만들어줍니다.


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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
@Controller
public class MailController {
    
    @Autowired
    JavaMailSender mailSender; //root-context에서 생성한 google mailsender 빈
    
    // mailSending 코드
      @RequestMapping(value = "/sendpass")
      public String mailSending(Model model,HttpServletResponse response) {
        Map<String, Object> map = model.asMap();
        UserDto userDto = (UserDto)map.get("resultDto");
        
        System.out.println(userDto.getbEmail());
        System.out.println(userDto.getbId());
        String setfrom = "springteam11@gmail.com";         
        String tomail  = userDto.getbEmail();     // 받는 사람 이메일
        String title   = userDto.getbNick() + "님의 아이디와 비밀번호 입니다.";      // 제목
        String content = userDto.getbNick() + "님의 아이디는 " 
                            + userDto.getbId()
                            + " 비밀번호는 "
                            + userDto.getbPass()
                            + " 입니다.";    // 내용
       
        try {
          MimeMessage message = mailSender.createMimeMessage();
          MimeMessageHelper messageHelper  = new MimeMessageHelper(message, true, "UTF-8"); //두번째 인자 true여야 파일첨부 가능.
     
          messageHelper.setFrom(setfrom);  // 보내는사람 생략하거나 하면 정상작동을 안함
          messageHelper.setTo(tomail);     // 받는사람 이메일
          messageHelper.setSubject(title); // 메일제목은 생략이 가능하다
          messageHelper.setText(content);  // 메일 내용
         
          mailSender.send(message);
          
          response.setContentType("text/html; charset=UTF-8");
          PrintWriter out = response.getWriter();
          out.println("<script>alert('성공적으로 메일을 발송했습니다.');history.go(-1);</script>");
          out.flush();
 
 
        } catch(Exception e){
          System.out.println(e);
        }
       
        return "login";
      }
    
}
cs


아까 1,2차 검증을 통과한경우 컨트롤러에서 return "redirce:sendpass"를 해주었는데, 그 요청을 이 컨트롤러가 받습니다.


아까 리다이렉트시 모델에 값을 담기 위해서 사용했던 RedirectAttributes 덕분에 우리는 이 컨트롤러에서 userDto의 값을 사용할수있게 됩니다.


메일 코드에 대한 자세한 내용은 구글링 해보시기 바랍니다 이것까지 쓰기에는 내용이 너무 많네요


댓글
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
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 31
글 보관함