일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 산술 연산자
- java
- 논리 연산자
- StringBuffer
- 연산자
- 함수
- 반복문
- 객체
- SQL 튜닝
- spring 게시판 삭제
- 객체지향
- 상속
- SQL
- 오버라이딩
- 자바의정석
- 인텔리제이 Web 애플리케이션
- 배열
- SpringSecurity 로그아웃
- 이클립스 설치
- 친절한 SQL 튜닝
- @PreAuthorize("isAuthenticated()")
- 친절한 SQL
- 예약어
- SpringSecurity 로그인
- join
- 비교 연산자
- 스프링시큐리티 로그아웃
- SQL튜닝
- 오버로딩
- 식별자
- Today
- Total
gi_dor
비밀번호 찾기 + 임시비밀번호 이메일전송 본문
스프링시큐리티에 PasswordEncoder를 통해 DB에 비밀번호는 암호화 되어있다
만약 사용자가 비밀번호를 잃어버렸다면 어떻게 처리해줘야할까 ?
0. 로그인 - 비밀번호를 잃어버렸다.
1. 사용자가 입력한 아이디와 이메일로 사용자 정보를 조회한다
- 성공 - POST
- 실패 - alert 로 알림창 띄워서 거부하기
입력한 값이 nul , 비어있는 공백
일치하지 않는 값으로 인해 사용자 정보 조회가 안될때
2. 임시비밀번호 만들기
- Random random 을 사용해 비밀번호 대소문자영어숫자특수문자로 최소8자 최대 16자를 생성하게 만들었다
- 아이디와 , 새로만들어진 비밀번호로 update 문으로 DB에 비밀번호 변경
3. 임시비밀번호 이메일 보내기
- MimeMessge 로 이메일 보내기 SimpleMessage를 사용한다면 정말간단한 text문 만 보낼수 있다
- html 파일을 보낼 것이기에 HtmlTemplate 만들기
4. 컨트롤러에서 처리하기
- 입력한 id , email 을 사용해 사용자 정보조회
- 조회한 사용자 정보의 email 로 임시 비밀번호 보내기
- 완료후 로그인 페이지로 이동
- 받은 이메일 확인후 로그인
<a href="/user/login/passwordReset" class="text-center" style="display: block;">비밀번호를 잊으셨나요?</a>
// 비밀번호 재설정 페이지로 이동하는 핸들러
@GetMapping("/login/passwordReset")
public String showPasswordResetPage() {
return "user/passwordResetForm"; // 비밀번호 재설정 폼으로 이동
}
<div class="row mb-3">
<div class="col-2"></div>
<div class="col-9">
<h4 style="text-align: center">비밀번호 찾기 </h4>
<br>
<form class="border bg-light mb-3" method="post" th:action="@{/user/login/passwordReset}">
<div class="form-group">
<div class="col-6 mb-3 ms-3 mt-3">
<label class="form-label">아이디</label>
<input type="text" class="form-control" name="id" />
</div>
</div>
<div class="form-group mb-3 ms-3">
<label class="form-label">이메일</label>
<div class="row">
<div class="col-3">
<input type="text" class="form-control" id="emailId" name="email1" placeholder="이메일 입력" />
<br>
</div>
@
<div class="col-4">
<select id="emailAddress" class="form-select" name="email2">
<option value="google.com">google.com</option>
<option value="naver.com">naver.com</option>
<option value="daum.net">daum.net</option>
</select>
</div>
<div class="col-3">
<button type="submit" id="resetButton" class="btn btn-secondary">비밀번호 찾기</button>
</div>
</div>
</div> <!-- <div class="form-group mb-3"> -->
</form>
</div>
<div class="col-1"></div>
</div>
<select id="selectUserByIdAndEmail" resultType="com.example.bookhub.user.vo.User">
SELECT
u.user_no as no,
u.user_id as id,
u.user_password as password,
u.user_name as name,
u.user_email as email ,
u.user_tel as tel ,
u.user_zip_code as zipCode ,
u.user_address as address ,
u.user_address_detail as addressDetail ,
u.user_created_date as createdDate,
u.user_updated_date as updatedDate ,
u.user_del_yn as delYn ,
u.user_point as point,
g.grade_no as "userGrade.no",
g.grade_name as "userGrade.name"
FROM USER u , USER_GRADE g
WHERE user_id = #{id}
and user_email = #{email}
and user_del_yn = 'N'
and u.grade_no = g.grade_no
</select>
<!-- 랜덤한 비밀번호로 받아서 변경하기 -->
<update id="updateResetPassword">
UPDATE USER
SET USER_PASSWORD = #{password}
WHERE USER_ID = #{id}
</update>
사실 select 로 저렇게 많은 컬럼 필요 없다 , id 와 pasword , email만 조회해도 된다
@Mapper
public interface UserMapper {
User selectUserByIdAndEmail(@Param("id") String id , @Param("email") String email);
void updateResetPassword(@Param("id") String id, @Param("password") String password);
}
@Service
@RequiredArgsConstructor
public class UserService implements UserDetailsService {
private final UserMapper userMapper;
private final PasswordEncoder passwordEncoder;
public User selectUserByIdAndEmail(String id, String email) {
User user = userMapper.selectUserByIdAndEmail(id,email);
if (user == null) {
throw new RuntimeException("해당 이메일에 해당하는 사용자를 찾을 수 없습니다: " + email);
}
return user;
}
// 예외 발생하면 롤백되서 이전 상태로 가게하려고 - ACID
@Transactional
public String resetPassword(String id , String email) {
User user = userMapper.selectUserByIdAndEmail(id, email);
if (user == null) {
throw new IllegalArgumentException("주어진 정보에 해당하는 사용자 정보가 없습니다.");
} else if (id == null || id.isEmpty() || email == null || email.isEmpty()) {
throw new IllegalArgumentException("아이디와 이메일을 모두 입력해야 합니다.");
}
// 임시 비밀번호 만들기
String resetPassword = RandomPassword.generatePassword(8,16);
// 비밀번호 변경 - 암호화 안되서 DB에 그냥 비밀번호 저장되버림
userMapper.updateResetPassword(id,passwordEncoder.encode(resetPassword));
return resetPassword;
}
}
passwordEncoder.encode를 해야 임시로받은 비밀번호를 암호화해서 DB에 저장된다 꼭 하자 꼭!!
@PostMapping("/login/passwordReset")
public String resetPassword(@RequestParam("id") String id,
@RequestParam("email1") String email1 ,
@RequestParam("email2") String email2 ,
Model model) {
try{
// 입력한 id,email 로 사용자 조회하기
String email = email1 + "@" + email2;
User user = userService.selectUserByIdAndEmail(id,email);
// 임시비밀번호 만들기 + DB에 update
String resetPassword = userService.resetPassword(id,email);
// 임시 비밀번호값 resetPassword
model.addAttribute("resetPassword",resetPassword);
// 사용자 조회한 값으로 eamil 보내기
String to = user.getEmail();
String subject = "BookHub 임시비밀번호 발급.";
String html = mailService.resetPasswordTemplate(resetPassword); // loadHtmlTemplate 메서드를 호출할 때는 괄호를 포함하여 호출해야 합니다.
mailService.sendEmail(to, subject, html);
return "/user/loginForm";
} catch (IllegalArgumentException aex) {
// 사용자 정보가 일치하지 않거나 누락된 경우 에러 메시지를 모델에 추가
model.addAttribute("error",aex.getMessage());
return "/user/passwordResetForm";
}
catch (Exception ex) {
return "/main";
}
}
입력한 email1 과 email2를 합쳐 String eamil 에 담은 이유는 User.vo 에 String email; 로 선언되어있기 때문이다
1. 입력한 id 와 eamil 로 DB에 저장되어있는 사용자의 정보를 조회한다
User user = userService.selectUserByIdAndEmail(id,email);
2. resetPassword 를 사용해 비밀번호를 새로 발급받은뒤 passwordEncoder 를 사용해 비밀번호를 암호화 처리
update 로 비밀번호를 변경한다
3. 암호화 처리하기전에 발급받은 임시비밀번호를 eamil에 보내보자
// 회원가입 완료시에 실행되는 회원가입완료 이메일 보내기
public void sendEmail(String to, String subject, String html) throws MessagingException {
MimeMessage message = javaMailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message,true);
helper.setTo(to);
helper.setSubject(subject);
helper.setText(html , true );
javaMailSender.send(message);
}
public String resetPasswordTemplate(String password) throws Exception{
ClassPathResource resource = new ClassPathResource("templates/user/mail/resetPassword.html");
String htmlTemplate = null;
try{
htmlTemplate = StreamUtils.copyToString(resource.getInputStream(), StandardCharsets.UTF_8);
} catch (IOException ex) {
System.err.println("이메일 템플릿을 로드하는 도중 오류가 발생했습니다.");
ex.printStackTrace();
}
return htmlTemplate.replace("PASSWORD", password);
}
- 첫번째 setTo(String... to ) 여러명에게 보낼 수 있다
- 두번째 setTo(String to) 한명에게 보낼 수 있다
public void sendSimpleEmail() {
SimpleMailMessage message = new SimpleMailMessage();
message.setSubject("임시비밀번호가 도착했습니다");
message.setTo("rltjs3563@naver.com");
message.setText("808");
javaMailSender.send(message);
}
Spring에서 제공하는 SimpleMailMessage 는 간단한 텍스트 기반 이메일을 생성하는 데 사용된다
복잡한 형식이나 첨부 파일 등을 다루지 않고, 단순한 텍스트 메시지만을 사용할 때 쓰인다
MimeMessage mimeMessage = javaMailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage,true);
1️⃣ MimeMessage: JavaMail의 MimeMessage 클래스를 확장하여 Spring의 이메일 전송 기능에 특화된 형태로 사용되는데 이메일의 제목, 본문, 첨부 파일 등을 다룰 때 사용한다
2️⃣ MimeMessageHelper: MimeMessage를 더 쉽게 생성하고 조작할 수 있도록 도와주는 헬퍼 클래스MimeMessageHelper는 MimeMessage를 생성하고 이메일의 수신자, 제목, 내용, 첨부 파일 등을 설정하는 데 도움을 준다. 또한 HTML 내용을 지원하고, 첨부 파일을 추가하는 등의 기능을 제공한다
resetPassword.html
<!DOCTYPE html>
<html lang="ko" xmlns:th="http://www.thymeleaf.org">
<head>
<title>::: 임시비밀번호 발급 :::</title>
</head>
<body style="margin: 0; padding: 0; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;">
<table align="center" border="0" cellpadding="0" cellspacing="0" width="100%" style="padding: 40px; background-color: #f9f9f9;">
<tr>
<td align="center" style="max-width: 20%;">
<!-- 브라우저에서 뜨는 사진에 경로를 입력해야한다고함 + localhost라 안될꺼라고함 -->
<!-- <img src="/static/image/login/logo.png" alt="BookHub 로고" style="max-width: 100%;">-->
</td>
</tr>
<tr>
<td align="center">
<!-- 텍스트로 회사 이름 표시 -->
<div style="font-size: 24px; font-weight: bold;">BookHub</div>
</td>
</tr>
<tr>
<td align="center" style="padding: 20px; font-size: 24px; font-weight: bold;">
임시 비밀번호가 발급 되었습니다.
</td>
</tr>
<tr>
<td align="center" style="padding: 10px; font-size: 32px; font-weight: bold; color: #333; background-color: #ffffff; border-radius: 5px; margin: 10px;">
임시비밀번호 : <span >PASSWORD</span>
</td>
</tr>
<tr>
<td align="center" style="font-size: 16px; padding: 30px;">
<p>제공해드린 비밀번호는 임시 비밀번호입니다</p>
<p>로그인 하신후에 마이 페이지에서 비밀번호를 변경한 뒤에 사이트를 이용해주세요</p>
<p>문의 사항이 있으시면 언제든지 저희에게 연락 주세요.</p>
</td>
</tr>
</table>
</body>
</html>
https://gi-dor.tistory.com/246
다양한 HTML 템플릿을 원한다면 추천 : https://unlayer.com/templates
'Back_End > SpringBoot' 카테고리의 다른 글
스프링부트 + MyBatis +MYSQL 페이징 처리 (0) | 2024.05.09 |
---|---|
스프링부트 설정파일(application.properties) 암호화 (Jasypt) (0) | 2024.05.02 |
마이페이지 ver.2- SpringSecurity, MySQL , MyBatis (1) | 2024.04.25 |
회원가입 - 아이디 중복체크 비동기 ajax (4) | 2024.04.25 |
암호화된 비밀번호 변경 (비동기) (0) | 2024.04.24 |