[๊ตฌํ] ์คํ๋ง์ผ๋ก ์ด๋ฉ์ผ ์ธ์ฆ ์ฝ๋ ๋ฐ๊ธ, ์ธ์ฆํ๊ธฐ
๊ณต๋ถํ๋ฉด์ ๋ง๋ค์๊ธฐ ๋๋ฌธ์ ํ๋ฆฐ ๋ถ๋ถ์ด๋ ๋ ์ข์ ๋ฐฉ๋ฒ์ด ์์ ์ ์์ต๋๋ค!
๊ตฌํ ํ ๋ด์ฉ
1)
- ๋ฉ์ผ ์ธ์ฆ ์ฝ๋๋ฅผ ๋ง๋ ๋ค.
- ํด๋น ๋ฉ์ผ๋ก ์ธ์ฆ ์ฝ๋๋ฅผ ๋ณด๋ธ๋ค.
2)
- ๋ฉ์ผ๋ก ์จ ์ธ์ฆ ์ฝ๋๋ฅผ ์ ๋ ฅํ๋ค.
- ๋ฉ์ผ๊ณผ ์ธ์ฆ ์ฝ๋ ์ผ์น ์ฌ๋ถ๋ฅผ ํ์ธํ๋ค.
1. ์์ด๋ ๋ง๋ค๊ธฐ
๋๋ Gmail SMTP Server๋ฅผ ์ด์ฉํ ๊ฒ์ด๋ค.
๊ฐ์ธ ์ด๋ฉ์ผ์ ์ฌ์ฉํ๊ธฐ๋ ์ข ๊ทธ๋ ๊ธฐ์ ์๋ก์ด ๊ณ์ ์ ํ๋ ๋ ๋ง๋ค๊ฒ์ด๋ค.
๊ณ์ ์ ๋ณด์์ด ๋ฎ์ ์ฑ์ ์ก์ธ์ค๋ฅผ ํ์ฉํด ์ฃผ์ด์ผ ํ๋ค๊ณ ํ๋ค.
2. Gmail SMTP Server ์ค์
build.gradleํ์ผ์ dependencies์ ๋ค์ ๋ฌธ์ฅ์ ์ถ๊ฐํด์ค๋ค.
implementation 'org.springframework.boot:spring-boot-starter-mail'
application.propertiesํ์ผ์ ๋ค์ ๋ฌธ์ฅ์ ์ถ๊ฐํด์ค๋ค.
spring.mail.host=smtp.gmail.com
spring.mail.port=587
spring.mail.username=(email)
spring.mail.password=(password)
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.auth=true
email, password๋ ๋ณธ์ธ ๊ฒ ๋ฃ์ผ๋ฉด ๋๋ค.
3. ์ธ์ฆ ์ฝ๋ ๋๋ฉ์ธ ์ํฐํฐ ๋ง๋ค๊ธฐ
verifycode๋ ์ฝ๋๊ฐ๊ณผ ์ฝ๋์ ์ด๋ฉ์ผ๋ก ์ด๋ฃจ์ด์ ธ ์๋ค.
์ฝ๋๋ ์๋์์ฑ์ด๋ฉฐ ์ด๋ฉ์ผ๊ณผ ์ฝ๋๊ฐ ๋ง๋์ง ์ฌ๋ถ๋ฅผ ํ์ธํ๊ธฐ ์ํจ์ด๋ค.
@Getter
@Entity
@Table
@AllArgsConstructor
@NoArgsConstructor
public class VerifyCode extends Timestamped{
@Id
@Column(name = "code")
@GeneratedValue(generator = RandomGenerator.generatorName)
@GenericGenerator(name = RandomGenerator.generatorName, strategy = "com.moment.CapturedMomentServer.util.RandomGenerator")
String code;
@Column(name = "email", unique = true)
String email;
public VerifyCode(VerifyCodeDto dto){
this.email = dto.getEmail();
}
}
randomgenerator๋ ๋ค๋ฅธ ๋ถ์ด ์ธํฐ๋ท์ ์ฌ๋ ค์ฃผ์ ์ฝ๋๋ฅผ ์ฌ์ฉํ์๋ค.
[java] ์์์ ์์ซ์ ๋ฌธ์์ด์ ์์ฑํ๋ ๋ฐฉ๋ฒ์ ๋ฌด์์ ๋๊น? - ๋ฆฌ๋ทฐ๋๋ผ
๋๋ ์ฐพ๊ณ ์์๋ค ์์ฌ ๋์ ์์ซ์ ๋ฌธ์์ด์ ์์ฑํ๋ ๊ฐ๋จํ Java ์๊ณ ๋ฆฌ์ฆ์ ์์ต๋๋ค. ๋ด ์ํฉ์์ ๊ทธ๊ฒ์ 500K+์ธ๋๋ฅผ ์ด์ํ์ฌ “์๋ง๋”๋ ์ฐฝ์ ์ธ ๊ณ ์ ์ธ์ / ํค ์๋ณ์๋ก ์ฌ์ฉ๋ฉ๋๋ค (ํ
daplus.net
์ธํฐ๋ท์ ๋ง์ด ๋๋ ์ฝ๋ ๊ฐ๊ธด ํ๋ฐ ์ด๋ฐ ์ฝ๋๋ฅผ ์ฐธ๊ณ ํ๊ณ 12์์ ๋๋ค ๋ฌธ์๋ฅผ ์์ฑํ๋ค.
UUID๋ ๋๋ฌด ๊ธธ์ด์ ์ฌ์ฉํ๊ฒ ๋์๋ค.
์ฒ์์๋ ์ด๋ฉ์ผ๋ง์ ์ ๋ ฅํ๋ฉด ์ฝ๋๊ฐ ์๋์์ฑ ๋ฐ๊ธ๋์ด์ผ ํ๋ฏ๋ก DTO๋ฅผ ๋ง๋ค๋๋ก ํ๊ฒ ๋ค.
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class VerifyCodeDto {
@NotNull
private String email; // ํ์ ๋๋ค์
}
4. ์ปจํธ๋กค๋ฌ ๋ง๋ค๊ธฐ
์ธ์ฆ ์ฝ๋ ๋ฉ์ผ ์ ์ก ์ปจํธ๋กค๋ฌ๋ถํฐ ๋ง๋ค์ด๋ณด๋๋ก ํ๊ฒ ๋ค.
@PostMapping(value = "/user/certification")
public ResponseEntity<HashMap> mailCheck(@RequestBody VerifyCodeDto codeDto){
//์ฝ๋ ์์ฑ & ์ ์ฅ
VerifyCode verifyCode = verifyCodeService.saveCode(codeDto);
//๋ฉ์ผ ์ ์ก
boolean success = mailService.checkEmail(verifyCode);
HashMap<String, Object> responseMap = new HashMap<>();
if(success) {
responseMap.put("status", 200);
responseMap.put("message", "๋ฉ์ผ ๋ฐ์ก ์ฑ๊ณต");
responseMap.put("code" , verifyCode.getCode());
return new ResponseEntity<HashMap> (responseMap, HttpStatus.OK);
}
else{
responseMap.put("status", 500);
responseMap.put("message", "๋ฉ์ผ ๋ฐ์ก ์คํจ");
return new ResponseEntity<HashMap> (responseMap, HttpStatus.CONFLICT);
}
}
verifyCodeService์์ ์ฝ๋๋ฅผ ์์ฑํด ์ ์ฅํ๋ค.
๋ค์ ์ฝ๋๋ฅผ mailService์์ ์ด๋ฉ์ผ๋ก ์ ์กํ๋ค.
5. VerifyCodeRepository
@Repository
public interface VerifyCodeRepository extends JpaRepository<VerifyCode, Long> {
public VerifyCode findByEmail(String email);
public VerifyCode findByCode(String code);
public boolean existsByEmail(String email);
public void deleteByEmail(String email);
}
6. VerifyCodeService
@Service
@Transactional
@AllArgsConstructor
public class VerifyCodeService {
private final VerifyCodeRepository repository;
...
public VerifyCode saveCode(VerifyCodeDto code){
if(repository.existsByEmail(code.getEmail()))
repository.deleteByEmail(code.getEmail());
return repository.save(new VerifyCode(code));
}
...
}
(์ด๋ฉ์ผ๋ง ๋ค์ด์๋) VerifyCodeDto๋ฅผ ๋ฐ์์
์ธ์ฆ ์ฝ๋๊ฐ ๋ฐ๊ธ๋์ด์๋ ์ด๋ฉ์ผ์ธ์ง ํ์ธํ๋ค.
๋ฐ๊ธ๋์ด ์๋ค๋ฉด, ๊ทธ ์ธ์ฆ์ฝ๋๋ ์ญ์ ํ๋ค.
๊ทธ๋ฆฌ๊ณ ์ฌํผ ๋ฐ์ ์ด๋ฉ์ผ๋ก new VerifyCode๋ฅผ ๋ง๋ค์ด์ ์ ์ธ์ฆ ์ฝ๋๋ฅผ ์์ฑํด์ค๋ค.
7. MailService
@Service
@RequiredArgsConstructor
public class MailService {
private final JavaMailSender javaMailSender;
private final PasswordEncoder passwordEncoder;
public boolean checkEmail(VerifyCode verifyCode){
if(verifyCode.getCode() == null)
return false;
SimpleMailMessage simpleMailMessage = new SimpleMailMessage();
simpleMailMessage.setTo(verifyCode.getEmail());
simpleMailMessage.setSubject("Captured-Moment ์ด๋ฉ์ผ ํ์ธ ์ฝ๋");
simpleMailMessage.setText("์ ํฌ ์๋น์ค์ ๊ฐ์
ํด ์ฃผ์
์ ๊ฐ์ฌํฉ๋๋ค.\n"
+ "์ด๋ฉ์ผ ํ์ธ ์ฝ๋๋ " + verifyCode.getCode() + " ์
๋๋ค.");
javaMailSender.send(simpleMailMessage);
return true;
}
...
}
JavaMailSender๋ฅผ ์ฌ์ฉํ๋ค.
To, Subject(์ ๋ชฉ), ๋ณด๋ผ Text๋ฅผ ์ค์ ํ๋ค.
๋ด์ฉ์ ์ ์ฝ๋์ ๊ฐ์ด ์ค์ ํ๋ค.
8. ํ ์คํธ
9. ์ปจํธ๋กค๋ฌ
๋ค์์ ์ ๋ ฅ๋ฐ์ ์ฝ๋๊ฐ ์ด ์ด๋ฉ์ผ๊ณผ ๋ง๋ ์ฝ๋์ธ์ง ํ์ธํ๋ ์ปจํธ๋กค๋ฌ๋ค.
@GetMapping(value = "/user/check")
public ResponseEntity<HashMap> mailCheck(@RequestBody VerifyCode verifyCode){
boolean check = verifyCodeService.check(verifyCode);
HashMap<String, Object> responseMap = new HashMap<>();
if(check){
verifyCodeService.deleteByEmail(verifyCode.getEmail());
responseMap.put("status", 200);
responseMap.put("message", "์ธ์ฆ ์ฑ๊ณต");
return new ResponseEntity<HashMap> (responseMap, HttpStatus.OK);
}
else{
responseMap.put("status", 401);
responseMap.put("message", "์๋ชป๋ ์ธ์ฆ ์ฝ๋");
return new ResponseEntity<HashMap> (responseMap, HttpStatus.CONFLICT);
}
}
๋ง๋์ง ์ฒดํฌํ๊ณ ๋ง๋ค๋ฉด ์ธ์ฆ์ฑ๊ณต, ํ๋ฆฌ๋ค๋ฉด ์ธ์ฆ ์ฝ๋๊ฐ ํ๋ ธ๋ค๋ ๋ฉ์ธ์ง๊ฐ ๋์จ๋ค.
๋ํ ์ธ์ฆ์ด ์ฑ๊ณตํ๋ค๋ฉด ํด๋น ์ธ์ฆ์ฝ๋๋ ์ง์๋ฒ๋ฆฐ๋ค. ๋ ์ด์ ์ธ๋ชจ๊ฐ ์๊ธฐ ๋๋ฌธ์ด๋ค.
10. VerifyCodeService
@Service
@Transactional
@AllArgsConstructor
public class VerifyCodeService {
private final VerifyCodeRepository repository;
public boolean check(VerifyCode code){
VerifyCode findCode = repository.findByEmail(code.getEmail());
if(findCode == null)
return false;
else if(code.getCode().equals(findCode.getCode()))
return true;
else
return false;
}
public void deleteByEmail(String email){
repository.deleteByEmail(email);
}
}
์ ๋ ฅ๋ ์ด๋ฉ์ผ๋ก ํด๋นํ๋ ์ฝ๋/์ด๋ฉ์ผ ์ธํธ (VerifyCode)๋ฅผ ์ฐพ์์จ๋ค.
์ฐพ์์ค์ง ๋ชปํ์ผ๋ฉด false๋ฅผ ๋ฆฌํดํ๋ค.
์ ๋ ฅ๋ ์ฝ๋์ ์ฐพ์ ์ฝ๋๊ฐ ๊ฐ์ผ๋ฉด true๋ฅผ ๋ฆฌํดํ๋ค.
๋๋ค ์๋๋ฉด false๋ฅผ ๋ฆฌํดํ๋ค.
11. ํ ์คํธ
์๋ชป๋๊ฑฐ ์ ๋ ฅํ๋ฉด ์ธ์ฆ ์๋๊ณ , ํ๋ฒ ๋ sendํด๋ ์ธ์ฆ ์๋๋ค.(์ง์๋ฒ๋ ค์) ๋!