본문 바로가기
토이 프로젝트

[토이 프로젝트 개발일지] 15. 비밀번호 재설정 링크 이메일 발송

by woorix2 2025. 5. 20.

1. 비밀번호 재설정 링크 이메일 발송

이름, 이메일(아이디), 생년월일만 가지고 비밀번호 재설정 페이지로 이동시키는 것이 아무래도 보안에 너무 취약한 것 같아서, 이메일로 재설정 링크를 발송하는 것으로 변경했다.

 

@PostMapping("/find-password")
	public ResponseEntity<?> findPassword(@RequestBody FindPasswordRequestDto dto) {
		Optional<User> user = userService.findUserForPasswordReset(dto);

		if (user.isEmpty()) {
			return ResponseEntity.status(HttpStatus.NOT_FOUND).body("일치하는 사용자가 없습니다");
		}

		String token = UUID.randomUUID().toString();
		String email = user.get().getEmail();

		redisTemplate.opsForValue().set("reset:" + token, email, Duration.ofMinutes(15));

		String resetLink = "URL/reset-password?token=" + token; 
		System.out.println("email " + email);
		emailService.sendResetLink(email, resetLink);
		return ResponseEntity.ok("비밀번호 재설정 링크를 이메일로 전송했습니다.");
	}

 

-토큰 생성 및 Redis 저장

1) 기존 회원이라면 UUID로 토큰을 생성하고, redis에 email과 함께 15분의 유효시간을 두어 저장한다.

 

-이메일 발송

2) emailService의 sendResetLink 메서드를 통해 토큰을 파라미터로 붙인 재설정 링크를 발송한다.

 

@GetMapping("/reset-password")
	public String resetPasswordPage(@RequestParam("token") String token, Model model) {
		String email = redisTemplate.opsForValue().get("reset:" + token);

		if (email == null) {
			model.addAttribute("error", "유효하지 않은 링크이거나 만료되었습니다.");
		}

		model.addAttribute("token", token);
		return "reset-password";
	}

 

-토큰 검증 및 재설정 페이지 진입
3) 재설정 페이지로 이동할 때, redis에서 파라미터로 받은 토큰으로 조회를 한다. 15분이 지나면 redis에 정보가 없어 만료 안내를 사용자에게 한다.

 

@PostMapping("/reset-password")
	public ResponseEntity<?> resetPassword(@RequestBody ResetPasswordRequestDto dto) {
		String email = redisTemplate.opsForValue().get("reset:" + dto.getToken());

		if (email == null) {
			return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("유효하지 않응 요청입니다.");
		}

		boolean success = userService.resetPassword(email, dto.getPassword());
		if (success) {
			redisTemplate.delete("reset:" + dto.getToken()); // 한 번 사용한 토큰 제거
			return ResponseEntity.ok("비밀번호가 성공적으로 변경되었습니다.");
		} else {
			return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("비밀번호 변경 실패");
		}
	}

 

-비밀번호 재설정 요청 및 토큰 제거

4) 비밀번호 재설정을 완료할 때, 화면에서 이전에 파라미터로 받은 토큰을 던지고, 다시 그걸 redis와 조회한다.

5) 이상이 없다면, 비밀번호를 재설정하고 토큰을 삭제한다.

 


이제 사용자는 이메일을 통해서만 비밀번호 재설정이 가능하다.

외부 접근 위험을 줄였다.