확인 사항
- JPA repository를 상속하는 MemberRepo에서 Member의 필드명과 다른 다르게 구성된 메서드가 있으면
- 멤버와 관련한 모든 클래스에 대해 "BeanCreatrion"가 발생한다.
- 똑같은 오류가 여러 번 발생했다.. 주의하기!.
- 오류 - 순환 참조
- 원인: Impl 클래스와 securityConfig 간에 순환하는 문제가 발생
<hide/>
The dependencies of some of the beans in the application context form a cycle:
┌─────┐
| securityConfiguration defined in file [C:\Users\Ran\Desktop\R\zerobase\remote_mall\build\classes\java\main\com\example\mall\configuration\SecurityConfiguration.class]
↑ ↓
| memberServiceImpl defined in file [C:\Users\Ran\Desktop\R\zerobase\remote_mall\build\classes\java\main\com\example\mall\service\MemberServiceImpl.class]
└─────┘
Action:
Relying upon circular references is discouraged and they are prohibited by default. Update your application to remove the dependency cycle between beans. As a last resort, it may be possible to break the cycle automatically by setting spring.main.allow-circular-references to true.
- 해결: SecurityConfig 클래스에서 선언한 멤버변수 MemberService를 지운다.
1. 로그인 History
- LoginHistory
<hide/>
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
@Builder
@Data // getter, setter
@Entity
public class LoginHistory {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String userId;
private LocalDateTime lastLoginTime;
private String clientIp;
private String userAgent;
}
- MemberServiceImpl
- 로그인 히스토리에 로그인한 계정의 ip와 접속한 기기 정보도 넣을 수 있다.
- RequestUtils를 이용한다.
<hide/>
@Override
public boolean authenticate(MemberInput parameter){
// user의 비번은 인코딩된 상태이다.member의 비번은 암호화되지 않은 상태
Member user = this.memberRepository.findByUserId(parameter.getUserId())
.orElseThrow(() -> new RuntimeException("존재하지 않는 ID 입니다."));
// 비번 확인
if(!this.passwordEncoder.matches(parameter.getPassword(), user.getPassword())){
throw new RuntimeException("비밀 번호가 일치하지 않습니다.");
}
return true;
}
- controller
- RequestUtils를 이용하기 위해서는 매개변수로 HttpServlet을 넣어야한다.
- 따라서 컨트롤러에 넣어줘야한다.
<hide/>
@PostMapping("/member/login")
public String loginSubmit(HttpServletRequest request,
Model model,
MemberInput memberInput){
boolean errorMessage = false;
if(memberService.login(memberInput, request) == null){
model.addAttribute("errorMassage", errorMessage);
return "member/login";
}
// 로그인 성공
errorMessage = true;
model.addAttribute("errorMassage", errorMessage);
return "index";
}
- HTML
<hide/>
<!DOCTYPE html>
<html lang="ko" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>회원 로그인</title>
</head>
<body>
<h1>회원 로그인</h1>
<div th:replace="/fragments/layout.html :: fragment-body-menu" ></div>
<div th:text="${errorMessage}">
<!-- UserAuthenticationFailureHandler 에서 넘겨 받은 변수-->
</div>
<div class="login">
<form method="post">
<table>
<tbody>
<tr>
<th>ID</th>
<td><input type="email" name="userId" placeholder="아이디(이메일)을 입력해주세요"/></td>
</tr>
<tr>
<th>Password</th>
<td><input type="password" name="password" placeholder="비밀번호 입력"/></td>
</tr>
</tbody>
</table>
<p/>
<div>
<button type="submit" >로그인</button>
</div>
<a href="/member/find-password">비밀번호 찾기</a>
<div>
</div>
</form>
</div>
</body>
</html>
Note) 실행 결과
- 로그인 성공 화면
- 로그인 실패 화면
- "로그인에 실패했습니다."라는 errorMessage는 UserAuthenticationFailureHandler에서 html 로 보내는 것이다.
- request.setAttribute("errorMessage", msg);
- 오류: 로그인 하고 나면 index 페이지로 가야하는데 사진처럼 내용만 index로 가고 url은 멤버 로그인으로 간다.
- 원인
- 해결
- 오류:
<hide/>
Parameter 0 of constructor in com.example.mall.component.MailComponents required a bean of type 'org.springframework.mail.javamail.JavaMailSender' that could not be found.
Action:
Consider defining a bean of type 'org.springframework.mail.javamail.JavaMailSender' in your configuration.
- 원인
- 해결
Ex) 로그아웃
- SecurityConfig
- 로그아웃 누른 다음에 인덱스 페이지로 이동하도록 설정한다.
<hide/>
http.logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/member/logout"))
.logoutSuccessUrl("/") // 로그아웃 성공하면 메인페이지 이동
.invalidateHttpSession(true); // 로그아웃했으니 새션 초기화
Note) 실행 결과
======================== 오류 ========================
<hide/>
Mail server connection failed; nested exception is com.sun.mail.util.MailConnectException: Couldn't connect to host, port: localhost, 25; timeout -1;
nested exception is:
java.net.ConnectException: Connection refused: connect. Failed messages: com.sun.mail.util.MailConnectException: Couldn't connect to host, port: localhost, 25; timeout -1;
nested exception is:
java.net.ConnectException: Connection refused: connect
- 오류: MailConnectionException
- 원인: SpringBoot와 메일 보내기를 같이 띄우면 시간이 초과되서 오류가 났다.
- 해결: 따라서, 스프링 부트를 띄우는 메인 함수에 메일 보내는 코드를 넣지 말고 다른 클래스에 넣는다.
- 오류: 잘못된 매인함수
<hide/>
@SpringBootApplication
public class MallApplication {
public static void main(String[] args) {
SpringApplication.run(MallApplication.class, args);
try {
Thread.sleep(3000L);
}catch (Exception e){
e.printStackTrace();
}
MailComponents mailComponents = new MailComponents(new JavaMailSenderImpl());
// mailComponents.sendMainTest();
mailComponents.sendMail("받는 사람@naver.com", "제목", "네용");
}
}
- Impl 클래스의 register()에 메일 보내는 코드 추가
<hide/>
// 메일 보내기
String email = parameter.getUserId();
String subject = "Online mall 가입을 축하드립니다.";
String text = "<p>Online mall 가입을 축하드립니다.</p>" +
"<p>아래 링크를 클릭하셔서 가입을 완료하세요.</p>" +
"<div><a target='_blank' href='http://localhost:8080/member/email-auth?id=" +
uuid +
"'>가입 완료</a></div>";
mailComponents.sendMail(email, subject, text);
return true;
}
Note) 실행 결과
2. 이메일 인증 구현하기
- Impl - register() 가입한 회원에게 이메일 보내기
- 위의 링크를 누르면 회원 상태가 활성화되도록 구현한다.
'Spring Projcect > [갠플] Online-mall' 카테고리의 다른 글
[6일차] 관리자 로그인, 상품 등록 (0) | 2022.09.28 |
---|---|
[5일차] 연관 관계 매핑 - 장바구니, 쿠폰 (0) | 2022.09.27 |
[3주차] 회원 가입, 로그인 (0) | 2022.09.23 |
[2주차] DB 연결 & 회원가입 구현 (0) | 2022.09.22 |
[1주차] 프로젝트 주제와 생성 과정 (0) | 2022.09.11 |