Skip to content

Commit

Permalink
๐Ÿ›[Fix] ๋กœ๊ทธ์ธํ•˜์ง€ ์•Š์€ ์‚ฌ์šฉ์ž๊ฐ€ ๋น„๋ฐ€๋ฒˆํ˜ธ ์žฌ์„ค์ •์„ ํ•  ๊ฒฝ์šฐ ์ž„์‹œ ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ๋ณธ์ธ ๋ฉ”์ผ๋กœ ๋ฐœ์†ก
Browse files Browse the repository at this point in the history
  • Loading branch information
rimi3226 committed Nov 3, 2024
1 parent ad4a6a0 commit 2d8936a
Show file tree
Hide file tree
Showing 6 changed files with 245 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public ApiResponse<String> sendEmailwithCheckDuplication(
String email = emailRequestDTO.getEmail();

authService.verifyEmailforNewUser(email);
authService.sendEmail(email);
authService.sendEmailVerification(email);
return ApiResponse.onSuccess("์ธ์ฆ ์ด๋ฉ”์ผ์„ ๋ฐœ์†กํ–ˆ์Šต๋‹ˆ๋‹ค.");
}

Expand All @@ -55,7 +55,7 @@ public ApiResponse<String> sendEmailwithCheckDuplication(
public ApiResponse<String> sendEmail(
@Valid @RequestBody MemberRequest.EmailRequestDTO emailRequestDTO) {
String email = emailRequestDTO.getEmail();
authService.sendEmail(email);
authService.sendEmailVerification(email);
return ApiResponse.onSuccess("์ธ์ฆ ์ด๋ฉ”์ผ์„ ๋ฐœ์†กํ–ˆ์Šต๋‹ˆ๋‹ค.");
}

Expand All @@ -68,7 +68,7 @@ public ApiResponse<String> sendEmailforUser(
// DB์— ์—†๋Š” ์‚ฌ์šฉ์ž์ผ ๊ฒฝ์šฐ ์—๋Ÿฌ ๋ฐœ์ƒ
authService.verifyEmailforExistUser(email);

authService.sendEmail(email);
authService.sendEmailVerification(email);
return ApiResponse.onSuccess("์ธ์ฆ ์ด๋ฉ”์ผ์„ ๋ฐœ์†กํ–ˆ์Šต๋‹ˆ๋‹ค.");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public ApiResponse<String> resetPasswordWithJWT(
public ApiResponse<String> resetPassword(
@Valid @RequestBody MemberRequest.PasswordRequestDTO passwordRequestDTO) {

passwordService.updatePasswordWithEmail(passwordRequestDTO.getEmail(), passwordRequestDTO.getOldPassword(), passwordRequestDTO.getNewPassword());
passwordService.updatePasswordWithEmail(passwordRequestDTO.getEmail());

return ApiResponse.onSuccess("๋น„๋ฐ€๋ฒˆํ˜ธ ์žฌ์„ค์ •์„ ์™„๋ฃŒํ–ˆ์Šต๋‹ˆ๋‹ค.");
}
Expand Down
4 changes: 0 additions & 4 deletions src/main/java/com/gamegoo/dto/member/MemberRequest.java
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,6 @@ public static class PasswordRequestDTO {
@Email(message = "Email ํ˜•์‹์ด ์˜ฌ๋ฐ”๋ฅด์ง€ ์•Š์Šต๋‹ˆ๋‹ค.")
@NotBlank(message = "Email์€ ๋น„์›Œ๋‘˜ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.")
String email;
@NotBlank(message = "newPassword๋Š” ๋น„์›Œ๋‘˜ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.")
String newPassword;
@NotBlank(message = "oldPassword๋Š” ๋น„์›Œ๋‘˜ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.")
String oldPassword;

}

Expand Down
6 changes: 3 additions & 3 deletions src/main/java/com/gamegoo/service/member/AuthService.java
Original file line number Diff line number Diff line change
Expand Up @@ -175,10 +175,10 @@ public void verifyEmailforExistUser(String email) {
* @param email
*/
@Transactional
public void sendEmail(String email) {
public void sendEmailVerification(String email) {

// ๋žœ๋ค ์ฝ”๋“œ ์ƒ์„ฑํ•˜๊ธฐ
String certificationNumber = CodeGeneratorUtil.generateRandomCode();
String certificationNumber = CodeGeneratorUtil.generateEmailRandomCode();

// ๋ฉ”์ผ ์ „์†กํ•˜๊ธฐ
sendEmailInternal(email, certificationNumber);
Expand Down Expand Up @@ -256,7 +256,7 @@ public void verifyEmail(String email, String code) {
* @param email
* @param certificationNumber
*/
private void sendEmailInternal(String email, String certificationNumber) {
public void sendEmailInternal(String email, String certificationNumber) {
try {
log.info("Starting email send process for email: {}, certificationNumber: {}", email,
certificationNumber);
Expand Down
206 changes: 196 additions & 10 deletions src/main/java/com/gamegoo/service/member/PasswordService.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,26 @@
import com.gamegoo.apiPayload.exception.handler.MemberHandler;
import com.gamegoo.domain.member.Member;
import com.gamegoo.repository.member.MemberRepository;
import com.gamegoo.util.CodeGeneratorUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;

@Service
@RequiredArgsConstructor
@Slf4j
public class PasswordService {

private final MemberRepository memberRepository;
private final BCryptPasswordEncoder bCryptPasswordEncoder;
private final JavaMailSender javaMailSender;


/**
* ๋น„๋ฐ€๋ฒˆํ˜ธ๊ฐ€ ๋งž๋Š”์ง€ ํ™•์ธ
Expand All @@ -29,7 +39,7 @@ public boolean checkPasswordById(Long userId, String password) {
}

/**
* ๋น„๋ฐ€๋ฒˆํ˜ธ ์ˆ˜์ •
* ๋น„๋ฐ€๋ฒˆํ˜ธ ์ˆ˜์ • (๋กœ๊ทธ์ธO)
*
* @param userId
* @param newPassword
Expand All @@ -49,28 +59,204 @@ public void updatePassword(Long userId, String oldPassword, String newPassword)
throw new MemberHandler(ErrorStatus.PASSWORD_INVALID);
}


}

/**
* ๋น„๋ฐ€๋ฒˆํ˜ธ ์ˆ˜์ •
* ๋น„๋ฐ€๋ฒˆํ˜ธ ์ˆ˜์ • (๋กœ๊ทธ์ธX)
*
* @param email
* @param newPassword
*/
public void updatePasswordWithEmail(String email, String oldPassword, String newPassword) {
// jwt ํ† ํฐ์œผ๋กœ ๋ฉค๋ฒ„ ์ฐพ๊ธฐ
public void updatePasswordWithEmail(String email) {
// email์œผ๋กœ ๋ฉค๋ฒ„ ์ฐพ๊ธฐ
Member member = memberRepository.findByEmail(email)
.orElseThrow(() -> new MemberHandler(ErrorStatus.MEMBER_NOT_FOUND));

// ๋žœ๋ค ์ž„์‹œ ๋น„๋ฐ€๋ฒˆํ˜ธ ์ƒ์„ฑ
String tempPassword = CodeGeneratorUtil.generatePasswordRandomCode();

// ์ด๋ฉ”์ผ ์ „์†ก
sendEmailInternal(email,tempPassword);

if (bCryptPasswordEncoder.matches(oldPassword,member.getPassword())) {
// ๋น„๋ฐ€๋ฒˆํ˜ธ ์žฌ์„ค์ •
member.updatePassword(bCryptPasswordEncoder.encode(newPassword));
member.updatePassword(bCryptPasswordEncoder.encode(tempPassword));
memberRepository.save(member);
}else{
throw new MemberHandler(ErrorStatus.PASSWORD_INVALID);
}

/**
* Gmail ๋ฐœ์†ก
*
* @param email
* @param tempPassword
*/
public void sendEmailInternal(String email, String tempPassword) {
try {
log.info("Starting email send process for email: {}, certificationNumber: {}", email,
tempPassword);

MimeMessage message = javaMailSender.createMimeMessage();
MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(message, true);

String htmlContent = getTempPasswordMessage(tempPassword);

mimeMessageHelper.setTo(email);
mimeMessageHelper.setSubject("GameGoo ์ž„์‹œ ๋น„๋ฐ€๋ฒˆํ˜ธ ๋ฐœ๊ธ‰");
mimeMessageHelper.setText(htmlContent, true);
log.debug("Prepared email message for email: {}", email);

javaMailSender.send(message);
log.info("Email sent successfully to email: {}", email);


} catch (MessagingException e) {
log.error("Failed to send email to email: {}, certificationNumber: {}, error: {}",
email, tempPassword, e.getMessage());

throw new MemberHandler(ErrorStatus.EMAIL_SEND_ERROR);
}
}

/**
* ๋ฉ”์ผ ๋‚ด์šฉ ํŽธ์ง‘
*
* @param tempPassword
* @return
*/
private String getTempPasswordMessage(String tempPassword) {
String certificationMessage = ""
+ "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n"
+
"<html xmlns=\"http://www.w3.org/1999/xhtml\">\n" +
" <head>\n" +
" <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n" +
" <title>Gamegoo ์ž„์‹œ ๋น„๋ฐ€๋ฒˆํ˜ธ ๋ฐœ๊ธ‰</title>\n" +
" <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n" +
" </head>\n" +
" <body>\n" +
" <table\n" +
" style=\"\n" +
" width: 628px;\n" +
" box-sizing: border-box;\n" +
" border-collapse: collapse;\n" +
" background-color: #ffffff;\n" +
" border: 1px solid #c0c0c0;\n" +
" text-align: left;\n" +
" margin: 0 auto;\n" +
" \"\n" +
" >\n" +
" <tbody>\n" +
" <tr>\n" +
" <td>\n" +
" <table\n" +
" cellpadding=\"0\"\n" +
" cellspacing=\"0\"\n" +
" style=\"width: 628px; height: 521px; padding: 53px 62px 42px 62px\"\n" +
" >\n" +
" <tbody>\n" +
" <tr>\n" +
" <td style=\"padding-bottom: 11.61px\">\n" +
" <img\n" +
" src=\"https://ifh.cc/g/BY3XG2.png\"\n" +
" style=\"display: block\"\n" +
" width=\"137\"\n" +
" height=\"24\"\n" +
" alt=\"Gamegoo\"\n" +
" />\n" +
" </td>\n" +
" </tr>\n" +
" <tr>\n" +
" <td style=\"padding-top: 20px\">\n" +
" <span\n" +
" style=\"\n" +
" color: #2d2d2d;\n" +
" font-family: Pretendard;\n" +
" font-size: 25px;\n" +
" font-style: normal;\n" +
" font-weight: 400;\n" +
" line-height: 150%;\n" +
" \"\n" +
" >\n" +
" ์ž„์‹œ ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ํ™•์ธํ•ด์ฃผ์„ธ์š”\n" +
" </span>\n" +
" </td>\n" +
" </tr>\n" +
" <tr>\n" +
" <td style=\"padding-top: 38px\">\n" +
" <span\n" +
" style=\"\n" +
" color: #5a42ee;\n" +
" color: #2d2d2d;\n" +
" font-size: 32px;\n" +
" font-style: normal;\n" +
" font-weight: 700;\n" +
" line-height: 150%;\n" +
" margin-bottom: 30px;\n" +
" \"\n" +
" >\n" +
tempPassword +
" </span>\n" +
" </td>\n" +
" </tr>\n" +
" <tr>\n" +
" <td style=\"padding-top: 30px\">\n" +
" <span\n" +
" style=\"\n" +
" color: #2d2d2d;\n" +
" font-family: Pretendard;\n" +
" font-size: 18px;\n" +
" font-style: normal;\n" +
" font-weight: 400;\n" +
" line-height: 150%;\n" +
" \"\n" +
" >\n" +
" ์ž„์‹œ ๋น„๋ฐ€๋ฒˆํ˜ธ๊ฐ€ ๋ฐœ๊ธ‰๋˜์—ˆ์Šต๋‹ˆ๋‹ค. \n" +
" ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค.\n" +
" </span>\n" +
" </td>\n" +
" </tr>\n" +
" </tbody>\n" +
" </table>\n" +
" <table\n" +
" cellpadding=\"0\"\n" +
" cellspacing=\"0\"\n" +
" style=\"\n" +
" width: 628px;\n" +
" height: 292px;\n" +
" padding: 37px 0px 153px 62px;\n" +
" background: #f7f7f9;\n" +
" \"\n" +
" >\n" +
" <tbody>\n" +
" <tr>\n" +
" <td>\n" +
" <span\n" +
" style=\"\n" +
" color: #606060;\n" +
" font-family: Pretendard;\n" +
" font-size: 11px;\n" +
" font-style: normal;\n" +
" font-weight: 500;\n" +
" line-height: 150%;\n" +
" \"\n" +
" >\n" +
" ๋ณธ ๋ฉ”์ผ์€ ๋ฐœ์‹  ์ „์šฉ์œผ๋กœ ํšŒ์‹ ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.<br />\n" +
" ๊ถ๊ธˆํ•˜์‹  ์ ์€ ๊ฒœ๊ตฌ ์ด๋ฉ”์ผ์ด๋‚˜ ์นด์นด์˜ค ์ฑ„๋„์„ ํ†ตํ•ด\n" +
" ๋ฌธ์˜ํ•˜์‹œ๊ธฐ ๋ฐ”๋ž๋‹ˆ๋‹ค.<br /><br />\n" +
" email: [email protected]<br />\n" +
" kakao: https://pf.kakao.com/_Rrxiqn<br />\n" +
" copyright 2024. GameGoo All Rights Reserved.<br />\n" +
" </span>\n" +
" </td>\n" +
" </tr>\n" +
" </tbody>\n" +
" </table>\n" +
" </td>\n" +
" </tr>\n" +
" </tbody>\n" +
" </table>\n" +
" </body>\n" +
"</html>\n";

return certificationMessage;
}

}
50 changes: 42 additions & 8 deletions src/main/java/com/gamegoo/util/CodeGeneratorUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,58 @@

public class CodeGeneratorUtil {

private static final String CHARACTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
private static final String UPPER_CASE = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
private static final String LOWER_CASE = "abcdefghijklmnopqrstuvwxyz";
private static final String DIGITS = "0123456789";
private static final String ALL_CHARACTERS = UPPER_CASE + LOWER_CASE + DIGITS;
private static final SecureRandom random = new SecureRandom();
private static final int CODE_LENGTH = 5;
private static final int EMAIL_CODE_LENGTH = 5;
private static final int PASSWORD_CODE_LENGTH = 12;

/**
* ์ด๋ฉ”์ผ ์ธ์ฆ์— ์‚ฌ์šฉํ•˜๋Š” ๋ฉ”์†Œ๋“œ : ๋žœ๋ค ์ฝ”๋“œ ๋งŒ๋“ค๊ธฐ
*
* @return
*/
public static String generateRandomCode() {
StringBuilder code = new StringBuilder(CODE_LENGTH);
for (int i = 0; i < CODE_LENGTH; i++) {
int index = random.nextInt(CHARACTERS.length());
code.append(CHARACTERS.charAt(index));
public static String generateEmailRandomCode() {
StringBuilder code = new StringBuilder(EMAIL_CODE_LENGTH);
for (int i = 0; i < EMAIL_CODE_LENGTH; i++) {
int index = random.nextInt(UPPER_CASE.length() + DIGITS.length());
code.append(UPPER_CASE.charAt(index % UPPER_CASE.length()));
}
System.out.println(code);
return code.toString();
}

/**
* ๋น„๋ฐ€๋ฒˆํ˜ธ ์žฌ์„ค์ •ํ•˜๋Š” ๋žœ๋ค ์ฝ”๋“œ ์ƒ์„ฑ
* @return
*/
public static String generatePasswordRandomCode(){
StringBuilder code = new StringBuilder(PASSWORD_CODE_LENGTH);

// ์ตœ์†Œํ•œ ํ•˜๋‚˜์˜ ๋Œ€๋ฌธ์ž, ์†Œ๋ฌธ์ž, ์ˆซ์ž, ํŠน์ˆ˜๋ฌธ์ž๋ฅผ ํฌํ•จํ•˜๋„๋ก ํ•จ
code.append(UPPER_CASE.charAt(random.nextInt(UPPER_CASE.length())));
code.append(LOWER_CASE.charAt(random.nextInt(LOWER_CASE.length())));
code.append(DIGITS.charAt(random.nextInt(DIGITS.length())));

// ๋‚˜๋จธ์ง€ ๊ธธ์ด๋ฅผ ๋žœ๋คํ•œ ๋ชจ๋“  ๋ฌธ์ž๋กœ ์ฑ„์›€
for (int i = 4; i < PASSWORD_CODE_LENGTH; i++) {
int index = random.nextInt(ALL_CHARACTERS.length());
code.append(ALL_CHARACTERS.charAt(index));
}

// ์ƒ์„ฑ๋œ ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ์„ž์–ด์„œ ๋ฐ˜ํ™˜
return shuffleString(code.toString());
}

private static String shuffleString(String input) {
char[] characters = input.toCharArray();
for (int i = 0; i < characters.length; i++) {
int randomIndex = random.nextInt(characters.length);
char temp = characters[i];
characters[i] = characters[randomIndex];
characters[randomIndex] = temp;
}
return new String(characters);
}
}

0 comments on commit 2d8936a

Please sign in to comment.