Hansel

스프링 로그인 로직 + SMTP 본문

프로젝트/과정

스프링 로그인 로직 + SMTP

핑슬 2022. 5. 9. 23:05

현재 로그인과 관련하여 해야할 기능은 다음과 같다.

=> 실패시 아이디 혹은 비밀번호를 확인하라는 메세지가 필요하다.(완료)
=> 한 아이디에 대해 너무 잦은 요청이 온다면 그 ID를 잠군다.(완료)
=> 비밀번호 찾기 기능을 추가한다.(현재)
=> 아이디가 잠긴 경우 이메일 인증을 통해 풀리도록 한다.

 

비밀번호 찾기 기능은 유저가 가입할때 사용한 이메일로 비밀번호 변경 URL을 보내주는 방식을 사용할 것이다.

3번과 4번은 모두 이메일 인증으로 해결되는 문제이니 SMTP만 잘 사용하여 해결하면 된다.

 

SMTP?

우선 SMTP는 TCP/IP 4계층의 응용계층에서 사용하는 프로토콜이다.

TCP에 기반을 둔 프로토콜로 메일을 전송할땐 SMTP

, 메일을 다운로드할때는 POP3나 IMAP 프로토콜을 사용한다고 한다.

 

우선 기본적으로 서버에서 메일을 전송할때 어떤 이메일 서비스 프로바이더를 사용할지 정해야한다.

구글, 네이버, 다음 등 많은 선택지가 있지만 가장 무난한 구글을 사용할 것이다.

 

진행하기 이전에 먼저 본인의 구글 계정 보안에 들어가서 2차 인증을 설정한 뒤 앱 비밀번호를 추가해주도록 하자.

 

기본 세팅

 

비밀번호 찾기를 누르면 이런 화면이 나오도록 설정했다.

 

 

아래는 메일과 관련된 클래스들에 대한 설명이다.

더보기

The interfaces and classes for Java mail support in the Spring framework are organized as follows:

  1. MailSender interface: the top-level interface that provides basic functionality for sending simple emails
  2. JavaMailSender interface: the subinterface of the above MailSender. It supports MIME messages and is mostly used in conjunction with the MimeMessageHelper class for the creation of a MimeMessage. It's recommended to use the MimeMessagePreparator mechanism with this interface.
  3. JavaMailSenderImpl class provides an implementation of the JavaMailSender interface. It supports the MimeMessage and SimpleMailMessage.
  4. SimpleMailMessage class: used to create a simple mail message including the from, to, cc, subject and text fields
  5. MimeMessagePreparator interface provides a callback interface for the preparation of MIME messages.
  6. MimeMessageHelper class: helper class for the creation of MIME messages. It offers support for images, typical mail attachments and text content in an HTML layout.

 

 

메일 전송을 위해 JavaMailSender를 사용해야한다. 빈 등록을 해주자.

 

야믈 설정도 해주자. Spring의 하위 레벨이다.

auth는 인증, TLS는 보안과 관련된 설정이다. 필요하니 true로 해주자.

https://javaee.github.io/javamail/docs/api/com/sun/mail/smtp/package-summary.html

 

com.sun.mail.smtp (JavaMail API documentation)

Class Summary  Class Description SMTPMessage This class is a specialization of the MimeMessage class that allows you to specify various SMTP options and parameters that will be used when this message is sent over SMTP. SMTPSSLTransport This class implemen

javaee.github.io

위 설정 내용을 포함한 자세한 설정 내용은 위 링크에서 확인할 수 있다.

 

단순 테스트를 위해 우선 아이디와 이메일이 존재하면 테스트 메일을 보내도록 해보자.

매우 잘 보내진다.

 

어떤 방식을 사용해야 할까

비밀번호 변경은 매우 민감한 문제이다.

따라서 다른 사람이 함부로 내 계정의 비밀번호를 바꿀 수 없도록 해야한다.

 

여기서 사용할 방식은 유저가 비밀번호 변경 메일을 전송하는 순간

해당 유저는 랜덤한 UUID를 갖게되며 그 UUID를 포함한 URL에서 비밀번호 변경이 이뤄질 수 있도록 할것이다.

 

도입

Controller

컨트롤러에서 비밀번호 찾기에 대한 요청이 오면 우선 해당 데이터를 받아 유효한 계정인지 확인한다.

계정이 유효하다면 해당 계정에 등록된 이메일로 비밀번호가 변경 가능한 URL을 전송한다.

check으로 반환되는 것은 해당 유저가 가진 UUID이다.

 

Service

sendMail에서 메일을 전송하는 행위가 일어난다.

일반 텍스트를 전송하는거라면 Mime은 필요하지 않다. 

Mime은 이미지나 첨부파일 혹은 HTML과 같은 텍스트 이상의 데이터를 첨부하고자 할때 필요한 방식이다.

 

Async 어노테이션이 붙은 이유는 메일 전송을 동기화 방식으로 사용한다면

메일이 전송된 후에야 다음 작업이 일어난다.

 

현재 나는 메일 전송 버튼을 누르면 메일이 전송되었다는 알림창이 나타나는데 

이 알림창이 메일이 전송된 후에 표시가 된다. 따라서 3~5초 정도 딜레이가 생긴다.

 

결국 다른 스레드에서 처리할 수 있도록 해줘야하는데 Async 어노테이션을 사용해 비동기 처리를 할 수 있다.

 

HTML은 이렇게 만들었다. 좀 이쁘게 하면 더 좋겠지만 지금 중요한건 기능이니 외적인 것은 조금 배제했다.

 

 

전송

위 데이터 중 로그인 아이디가 abcd, 이메일이 k로 시작하는 유저의 비밀번호를 변경할 것이다.

 

전송 직후
받은 이메일
변경 화면

변경하기 직전 DB의 데이터에 UUID가 추가되어있다. URL에 포함된 UUID와 같은것을 확인할 수 있다.

 

비밀번호 변경

서비스단에서 해당 UUID를 가진 유저의 계정을 찾고 계정이 존재한다면 기존의 로그인 실패 시도 횟수, 잠금 여부, 가진 uuid를 모두 초기화시키고 새로 받은 비밀번호로 변경시켜준다.

 

기존 DB에 저장된 유저의 암호화된 비밀번호가 달라진 것을 확인할 수 있다.

uuid도 초기화됐다.

 

후기

우선 smtp를 이용한 비밀번호 변경 방식은 장고에서도 해봤던 방식이라 조금 익숙했다.

 

 

현재 방식에선 /reset-password/UUID 부분의 UUID에 아무 문자열이나 입력해도 비밀번호 변경 화면으로 이동이 된다.

변경을 시도해도 해당 UUID를 가진 계정이 없어 아무런 일도 일어나진 않는다.

 

하지만 저 URL이 공개되어 있는 것은 뭔가 마음에 들지 않는다.

막을 수 있는 방법을 생각해봐야 할 듯 싶다.