Skip to content

Commit

Permalink
Feat: 이메일 인증 기능 구현
Browse files Browse the repository at this point in the history
Issues #4
  • Loading branch information
rkddnr05 committed Aug 31, 2023
1 parent 8726a9d commit a1a772e
Show file tree
Hide file tree
Showing 16 changed files with 287 additions and 15 deletions.
3 changes: 2 additions & 1 deletion .idea/compiler.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions .idea/gradle.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 6 additions & 4 deletions server/008main_project/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,20 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'org.springframework.boot:spring-boot-starter-web'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
implementation 'org.springdoc:springdoc-openapi-ui:1.6.15'
implementation 'org.mapstruct:mapstruct:1.5.3.Final'
annotationProcessor 'org.mapstruct:mapstruct-processor:1.5.3.Final'
implementation 'org.mapstruct:mapstruct:1.5.5.Final' //버전 수정
annotationProcessor 'org.mapstruct:mapstruct-processor:1.5.5.Final' //추가
runtimeOnly 'com.h2database:h2'
runtimeOnly 'com.mysql:mysql-connector-j'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
// security 작업을 위한 의존성
implementation 'org.springframework.boot:spring-boot-starter-mail:2.7.0' //mail 전송을 위한 추가
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'com.google.code.gson:gson:2.8.8' // gson 의존성 추가
implementation 'org.springframework.boot:spring-boot-starter-security'
testImplementation 'org.springframework.security:spring-security-test'
// implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'io.jsonwebtoken:jjwt-api:0.11.5'
runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.11.5'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.stockholm.main_project.auth.mail;

import com.stockholm.main_project.auth.mail.Dto.ConfirmPostDto;
import com.stockholm.main_project.auth.mail.Dto.SendEmailPostDto;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

@Slf4j
@RequiredArgsConstructor
@RestController
public class AccountController {

private final EmailService emailService;


@PostMapping("/email/send")
public String emailConfirm(@RequestBody SendEmailPostDto sendEmailPostDto) throws Exception {

String confirm = emailService.sendSimpleMessage(sendEmailPostDto.getEmail());

return confirm;
}

@PostMapping("/email/confirm")
public ResponseEntity<String> emailConfirm(@RequestBody ConfirmPostDto confirmPostDto) throws Exception {
// 사용자가 입력한 코드(code)와 생성된 코드(ePw)를 비교
String email = confirmPostDto.getEmail();
String code = confirmPostDto.getCode();

if (code.equals(EmailServiceImpl.ePw)) {
return ResponseEntity.status(HttpStatus.OK).body("인증 성공");
} else {
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("인증 실패");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.stockholm.main_project.auth.mail.Dto;

import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class ConfirmPostDto {
private String email;
private String code;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.stockholm.main_project.auth.mail.Dto;

import lombok.Getter;
import lombok.Setter;

import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Pattern;

@Getter
@Setter
public class SendEmailPostDto {

@Email
@NotBlank
@Pattern(regexp = "^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+$",
message = "올바른 이메일 구성이 아닙니다.")
private String email;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package com.stockholm.main_project.auth.mail;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.JavaMailSenderImpl;

import java.util.Properties;

@Configuration
@PropertySource("classpath:stockholmMail.properties")
public class EmailConfig {

@Value("${mail.smtp.port}")
private int port;
@Value("${mail.smtp.socketFactory.port}")
private int socketPort;
@Value("${mail.smtp.auth}")
private boolean auth;
@Value("${mail.smtp.starttls.enable}")
private boolean starttls;
@Value("${mail.smtp.starttls.required}")
private boolean startlls_required;
@Value("${mail.smtp.socketFactory.fallback}")
private boolean fallback;
@Value("${AdminMail.id}")
private String id;
@Value("${AdminMail.password}")
private String password;

@Bean
public JavaMailSender javaMailService() {
JavaMailSenderImpl javaMailSender = new JavaMailSenderImpl();
javaMailSender.setHost("smtp.gmail.com");
javaMailSender.setUsername(id);
javaMailSender.setPassword(password);
javaMailSender.setPort(port);
javaMailSender.setJavaMailProperties(getMailProperties());
javaMailSender.setDefaultEncoding("UTF-8");
return javaMailSender;
}
private Properties getMailProperties()
{
Properties pt = new Properties();
pt.put("mail.smtp.socketFactory.port", socketPort);
pt.put("mail.smtp.auth", auth);
pt.put("mail.smtp.starttls.enable", starttls);
pt.put("mail.smtp.starttls.required", startlls_required);
pt.put("mail.smtp.socketFactory.fallback",fallback);
pt.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
return pt;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.stockholm.main_project.auth.mail;

public interface EmailService {
String sendSimpleMessage(String to)throws Exception;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package com.stockholm.main_project.auth.mail;

import lombok.Getter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.MailException;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Service;

import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import java.util.Random;

@Service
public class EmailServiceImpl implements EmailService{

@Autowired
JavaMailSender emailSender;

public static final String ePw = createKey();

private MimeMessage createMessage(String to)throws Exception{
System.out.println("보내는 대상 : "+ to);
System.out.println("인증 번호 : "+ePw);
MimeMessage message = emailSender.createMimeMessage();

message.addRecipients(MimeMessage.RecipientType.TO, to);//보내는 대상
message.setSubject("이메일 인증 테스트");//제목

String msgg="";
msgg+= "<div style='margin:20px;'>";
msgg+= "<h1> 안녕하세요 Stockholm입니다. </h1>";
msgg+= "<br>";
msgg+= "<p>아래 코드를 복사해 입력해주세요<p>";
msgg+= "<br>";
msgg+= "<p>감사합니다.<p>";
msgg+= "<br>";
msgg+= "<div align='center' style='border:1px solid black; font-family:verdana';>";
msgg+= "<h3 style='color:blue;'>회원가입 인증 코드입니다.</h3>";
msgg+= "<div style='font-size:130%'>";
msgg+= "CODE : <strong>";
msgg+= ePw+"</strong><div><br/> ";
msgg+= "</div>";
message.setText(msgg, "utf-8", "html");//내용
message.setFrom(new InternetAddress("[email protected]","Stockholm"));//보내는 사람

return message;
}

public static String createKey() {
StringBuffer key = new StringBuffer();
Random rnd = new Random();

for (int i = 0; i < 8; i++) { // 인증코드 8자리
int index = rnd.nextInt(3); // 0~2 까지 랜덤

switch (index) {
case 0:
key.append((char) ((int) (rnd.nextInt(26)) + 97));
// a~z (ex. 1+97=98 => (char)98 = 'b')
break;
case 1:
key.append((char) ((int) (rnd.nextInt(26)) + 65));
// A~Z
break;
case 2:
key.append((rnd.nextInt(10)));
// 0~9
break;
}
}
return key.toString();
}
@Override
public String sendSimpleMessage(String to)throws Exception {
// TODO Auto-generated method stub
MimeMessage message = createMessage(to);
try{//예외처리
emailSender.send(message);
}catch(MailException es){
es.printStackTrace();
throw new IllegalArgumentException();
}
return ePw;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@
import com.stockholm.main_project.member.dto.MemberPostDto;
import com.stockholm.main_project.member.entity.Member;
import com.stockholm.main_project.member.mapper.MemberMapper;
import com.stockholm.main_project.member.repository.MemberRepository;
import com.stockholm.main_project.member.service.MemberService;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;

@RestController
@RequestMapping("/members")
public class MemberController {
Expand All @@ -23,7 +24,7 @@ public MemberController(MemberService memberService, MemberMapper mapper) {
}

@PostMapping
public ResponseEntity postUser(@RequestBody MemberPostDto memberPostDto){
public ResponseEntity postUser(@Valid @RequestBody MemberPostDto memberPostDto){
Member member = mapper.memberPostToMember(memberPostDto);

Member response = memberService.createMember(member);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,32 @@
package com.stockholm.main_project.member.dto;

import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

import javax.validation.constraints.Email;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.*;

@Getter
@Setter
public class MemberPostDto {
@Email
@NotBlank
@Pattern(regexp = "^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+$",
message = "올바른 이메일 구성이 아닙니다.")
private String email;

@NotBlank
private String name;

@Pattern(regexp = "^(?=.*[A-Za-z])(?=.*\\d)(?=.*[@$!%*#?&])[A-Za-z\\d@$!%*#?&]{8,}$",
message = "1자 이상의 문자, 1개 이상의 숫자, 1개 이상의 특수문자를 포함하고 8자리 이상이어야 합니다.")
@NotBlank
private String password;

@Pattern(regexp = "^(?=.*[A-Za-z])(?=.*\\d)(?=.*[@$!%*#?&])[A-Za-z\\d@$!%*#?&]{8,}$",
message = "1자 이상의 문자, 1개 이상의 숫자, 1개 이상의 특수문자를 포함하고 8자리 이상이어야 합니다.")
@NotBlank
private String confirmPassword;


}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import java.util.ArrayList;
import java.util.List;

@Entity(name = "members")
@Entity
@Getter
@Setter
public class Member extends Auditable {
Expand All @@ -26,6 +26,9 @@ public class Member extends Auditable {
@Column(length = 255, nullable = false)
private String password;

@Transient
private String confirmPassword; //실제 저장을 하지 않기 위해 @Transient 사용

@Enumerated(value = EnumType.STRING)
@Column(length = 20, nullable = false)
private MemberStatus memberStatus = MemberStatus.MEMBER_ACTIVE;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,13 @@
import com.stockholm.main_project.member.dto.MemberPostDto;
import com.stockholm.main_project.member.dto.MemberResponseDto;
import com.stockholm.main_project.member.entity.Member;
import com.stockholm.main_project.member.repository.MemberRepository;
import org.mapstruct.Mapper;

@Mapper(componentModel = "spring")
public interface MemberMapper {

Member memberPostToMember(MemberPostDto requestBody);

Member memberPatchToMember(MemberPatchDto requestBody);

MemberResponseDto memberToMemberResponseDto(Member member);


}

Loading

0 comments on commit a1a772e

Please sign in to comment.