Skip to content

Commit

Permalink
refactor: 비밀번호 찾기 시 문자 인증을 받도록 변경
Browse files Browse the repository at this point in the history
  • Loading branch information
dgjinsu committed Oct 19, 2024
1 parent 4ba45a8 commit 08ad521
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@
import io.swagger.v3.oas.annotations.Operation;
import java.util.List;
import jikgong.domain.member.dto.company.CompanySearchResponse;
import jikgong.domain.member.dto.info.AuthCodeForFindRequest;
import jikgong.domain.member.dto.info.CompanyInfoRequest;
import jikgong.domain.member.dto.info.CompanyInfoResponse;
import jikgong.domain.member.dto.info.LoginIdAuthCodeRequest;
import jikgong.domain.member.dto.info.LoginIdFindRequest;
import jikgong.domain.member.dto.info.LoginIdFindResponse;
import jikgong.domain.member.dto.info.PasswordFindRequest;
import jikgong.domain.member.dto.info.PasswordFindResponse;
import jikgong.domain.member.dto.info.PasswordUpdateRequest;
import jikgong.domain.member.dto.info.WorkerInfoRequest;
import jikgong.domain.member.dto.info.WorkerInfoResponse;
Expand Down Expand Up @@ -84,24 +85,32 @@ public ResponseEntity<Response> updatePassword(@AuthenticationPrincipal Principa

@Operation(summary = "아이디 찾기 전 본인 인증")
@PostMapping("/api/member-info/loginId-verification")
public ResponseEntity<Response> verificationFindLoginId(@RequestBody LoginIdFindRequest request) {
public ResponseEntity<Response> verificationBeforeFindLoginId(@RequestBody LoginIdFindRequest request) {
memberInfoService.verificationBeforeFindLoginId(request);
return ResponseEntity.ok(new Response("아이디 찾기 인증 코드 발송 완료"));
}

@Operation(summary = "아이디 찾기", description = "본인 인증으로 발송된 authCode를 사용하여 아이디 찾기")
@PostMapping("/api/member-info/loginId/retrieve")
public ResponseEntity<Response> findLoginId(@RequestBody LoginIdAuthCodeRequest request) {
public ResponseEntity<Response> findLoginId(@RequestBody AuthCodeForFindRequest request) {
LoginIdFindResponse loginIdFindResponse = memberInfoService.findLoginId(request);
return ResponseEntity.ok(new Response(loginIdFindResponse, "비밀번호 확인 완료"));
}

@Operation(summary = "비밀번호 찾기 (임시 발급)", description = "sms로 임시 비밀번호 발급")
@PostMapping("/api/member-info/password-reset")
public ResponseEntity<Response> findPassword(@RequestBody PasswordFindRequest request)
@Operation(summary = "비밀번호 찾기 전 본인 인증")
@PostMapping("/api/member-info/password-verification")
public ResponseEntity<Response> verificationBeforeFindPassword(@RequestBody PasswordFindRequest request)
throws Exception {
memberInfoService.sendTemporaryPassword(request);
return ResponseEntity.ok(new Response("sms로 임시 비밀번호 발급 및 비밀번호 업데이트 완료"));
memberInfoService.verificationBeforeFindPassword(request);
return ResponseEntity.ok(new Response("비밀번호 찾기 인증 코드 발송 완료"));
}

@Operation(summary = "비밀번호 임시 발급", description = "문자 인증 코드 입력 후 임시 비밀번호 발급")
@PostMapping("/api/member-info/password-temporary")
public ResponseEntity<Response> updateTemporaryPassword(@RequestBody AuthCodeForFindRequest request)
throws Exception {
PasswordFindResponse passwordFindResponse = memberInfoService.updateTemporaryPassword(request);
return ResponseEntity.ok(new Response(passwordFindResponse, "임시 비밀번호로 업데이트 및 반환 완료"));
}

@Operation(summary = "체류 만료일 불러오기", description = "codef api를 활용하여 체류 만료일 정보 저장")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package jikgong.domain.member.dto.info;

import lombok.Builder;
import lombok.Getter;

@Builder
@Getter
public class PasswordFindResponse {

private String temporaryPassword;

public static PasswordFindResponse from(String temporaryPassword) {
return PasswordFindResponse.builder()
.temporaryPassword(temporaryPassword)
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,10 @@ public interface MemberRepository extends JpaRepository<Member, Long> {
@Query("select m from Member m where m.phone = :phone and " +
"(m.workerInfo.workerName = :name or m.companyInfo.companyName = :name)")
Optional<Member> findMemberForForgottenLoginId(@Param("phone") String phone, @Param("name") String name);

/**
* 비밀번호 찾기
*/
@Query("select m from Member m where m.loginId = :loginId and m.phone = :phone")
Optional<Member> findMemberForForgottenPassword(@Param("loginId") String loginId, @Param("phone") String phone);
}
45 changes: 33 additions & 12 deletions src/main/java/jikgong/domain/member/service/MemberInfoService.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import jikgong.domain.member.dto.company.CompanySearchResponse;
import jikgong.domain.member.dto.info.AuthCodeForFindRequest;
import jikgong.domain.member.dto.info.CompanyInfoRequest;
import jikgong.domain.member.dto.info.CompanyInfoResponse;
import jikgong.domain.member.dto.info.LoginIdAuthCodeRequest;
import jikgong.domain.member.dto.info.LoginIdFindRequest;
import jikgong.domain.member.dto.info.LoginIdFindResponse;
import jikgong.domain.member.dto.info.PasswordFindRequest;
import jikgong.domain.member.dto.info.PasswordFindResponse;
import jikgong.domain.member.dto.info.PasswordUpdateRequest;
import jikgong.domain.member.dto.info.WorkerInfoRequest;
import jikgong.domain.member.dto.info.WorkerInfoResponse;
Expand Down Expand Up @@ -145,24 +146,44 @@ public List<CompanySearchResponse> searchCompany(String keyword) {
}

/**
* 임시 비밀번호 생성
* 비밀번호 찾기 전 문자 인증
*/
public void sendTemporaryPassword(PasswordFindRequest request) throws Exception {
Member member = memberRepository.findByLoginId(request.getLoginId())
public void verificationBeforeFindPassword(PasswordFindRequest request) throws Exception {
Member member = memberRepository.findMemberForForgottenPassword(request.getLoginId(), request.getPhone())
.orElseThrow(() -> new JikgongException(ErrorCode.MEMBER_NOT_FOUND));

// 휴대폰 번호 확인
if (member.getPhone().equals(request.getPhone())) {
throw new JikgongException(ErrorCode.MEMBER_PHONE_NOT_MATCH);
// 6자리 랜덤 코드 생성
String authCode = RandomCode.createAuthCode();
String content = "[직공]\n비밀번호 찾기 본인확인 인증번호: [" + authCode + "]";
try {
smsService.sendSms(member.getPhone(), content);
} catch (Exception e) {
throw new JikgongException(ErrorCode.SMS_SEND_FAIL);
}

// Redis에 인증 코드와 회원 정보를 저장 (TTL 5분)
redisTemplate.opsForValue().set(member.getPhone(), authCode, 5, TimeUnit.MINUTES);
}

/**
* 임시 비밀번호 발급
*/
public PasswordFindResponse updateTemporaryPassword(AuthCodeForFindRequest request) {
// Redis에 저장된 인증 코드 가져오기
String savedAuthCode = redisTemplate.opsForValue().get(request.getPhone());

// 인증 코드가 일치하는지 체크
if (savedAuthCode == null || !savedAuthCode.equals(request.getAuthCode())) {
throw new JikgongException(ErrorCode.MEMBER_INVALID_AUTH_CODE); // 인증 코드 불일치
}

// 임시 비밀번호 생성
// 임시 번호 생성, 업데이트 및 반환
String temporaryPassword = RandomCode.createTemporaryPassword();
String content = "[직공]\n발급된 임시 비밀번호: [" + temporaryPassword + "]";
Member member = memberRepository.findByPhone(request.getPhone())
.orElseThrow(() -> new JikgongException(ErrorCode.MEMBER_NOT_FOUND));
member.updatePassword(encoder.encode(temporaryPassword));

// 임시 비밀번호 발송
smsService.sendSms(member.getPhone(), content);
return PasswordFindResponse.from(temporaryPassword);
}

/**
Expand All @@ -188,7 +209,7 @@ public void verificationBeforeFindLoginId(LoginIdFindRequest request) {
/**
* 문자로 인증된 코드로 아이디 찾기
*/
public LoginIdFindResponse findLoginId(LoginIdAuthCodeRequest request) {
public LoginIdFindResponse findLoginId(AuthCodeForFindRequest request) {
// Redis에 저장된 인증 코드 가져오기
String savedAuthCode = redisTemplate.opsForValue().get(request.getPhone());

Expand Down
3 changes: 1 addition & 2 deletions src/main/java/jikgong/global/exception/ErrorCode.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,7 @@ public enum ErrorCode {
MEMBER_UNAUTHORIZED(HttpStatus.UNAUTHORIZED, "MEMBER-009", "인증이 필요합니다."),
MEMBER_FORBIDDEN(HttpStatus.FORBIDDEN, "MEMBER-010", "권한이 필요합니다."),
MEMBER_CONSENTS_NEED_TO_AGREE(HttpStatus.FORBIDDEN, "MEMBER-011", "회원가입을 위해선 각종 내용에 동의해야합니다."),
MEMBER_PHONE_NOT_MATCH(HttpStatus.BAD_REQUEST, "MEMBER-012", "회원 정보에 입력된 핸드폰 번호와 일치하지 않습니다."),
MEMBER_INVALID_AUTH_CODE(HttpStatus.BAD_REQUEST, "MEMBER-013", "아이디를 찾기 위해 입력한 인증 코드가 올바르지 않습니다."),
MEMBER_INVALID_AUTH_CODE(HttpStatus.BAD_REQUEST, "MEMBER-012", "아이디를 찾기 위해 입력한 인증 코드가 올바르지 않습니다."),

/**
* 알림
Expand Down

0 comments on commit 08ad521

Please sign in to comment.