SecurityConfiguration
에 설정되어 있는 CustomFilterConfigurer
PasswordEncoder가 빈으로 등록되어 있는 상황
AccountDetailService
에 구현되어 있는 loadUserByUsername
과 AccountDetails
IllegalArgumentException: There is no PasswordEncoder mapped for the id "null"
JwtAuthenticationFilter.attemptAuthentication(JwtAuthenticationFilter.java:52) ~[main/:na]
return authenticationManager.authenticate(authenticationToken);
에서 예외가 출력되는 것으로 보인다.해결방법1 요약
CustomUserDetailsService implements UserDetailsService
에서PasswordEncoder
객체를 의존성 주입받아 커스텀UserDetails를 생성할 때 인코딩된 비밀번호를 세팅하도록 함.
현재 나의 class AccountDetailService implements UserDetailsService
코드 상태
디버깅 :
그러나 해결방법 1은 적절한 해결책이 아닌 것처럼 보인다. 이미 PasswordEncoder.encode
로 암호화되어 DB에서 저장된 유저 정보로 새로운 UserDetails를 만드는 것인데 여기서 한 번 더 암호화 과정을 추가할 이유가 없다.
그래도 한 번 시도해보자,
역시나 마찬가지로 가입한 다음, 로그인 인증 요청을 보냈으나 똑같은 예외가 발생했다.
다시 원상복구하자.
- 암호화 방식을 명시해서 return하는 방향으로 비밀번호를 만들어야 한다고 한다.
그러나 DB에 정상적으로 암호화방식이 명시화되어 저장되었기 때문에 위와 같은 상황은 부합하지 않는다.
MemberDetails를 구현할 때 생성자로 초기화하는 값 확인하기
MemberDetails
의 생성자에서는Member
엔티티 객체로부터 값을 받아서this
(MemberDetails)의 필드값으로 넘겨주어야 한다. 그에 따라 로그인 인증절차를 수행하는 것이다.
기존 내 코드
- AccountDetails에 account의 필드값 정보를 넘겨 인증절차를 수행해야 하는데,
기존의 내 코드는 account를 다시 builder 패턴으로 재구성한 의미 없는 코드이다.
핵심은 AccountDetails의 필드에 인자로 전달받은 account 객체의 정보를 전달하는 것임을 기억하자!
private final class AccountDetails extends Account implements UserDetails {
public AccountDetails(Account account) {
account.builder()
.account_id(account.getAccount_id())
.email(account.getEmail())
.password(account.getPassword())
.roles(account.getRoles())
.build();
}
- 빌더로 객체를 구성해봐도
this
(현재 생성된AccountDetails
의 객체)에 필드값이 반영되지 않는다.
(필드 값이 받아와지지 않는모습)
- Lombok 라이브러리로 생성되는 builder 패턴을 상속 받는 것의 문제인지, builder패턴 자체의 태생적인 한계인지는 알 수 없어서 자료를 찾아보았다.
- 참고: Lombok @Builder 상속
- 상속 관계에서 @Builder 적용
private final class AccountDetails extends Account implements UserDetails {
public AccountDetails(Account account) {
AccountDetails.builder()
.account_id(account.getAccount_id())
.email(account.getEmail())
.password(account.getPassword())
.roles(account.getRoles())
.build();
}
@Setter
를 부여한 후,private final class AccountDetails extends Account implements UserDetails {
public AccountDetails(Account account) {
setAccount_id(account.getAccount_id());
setEmail(account.getEmail());
setPassword(account.getPassword());
setRoles(account.getRoles());
}
회원가입
로그인
응답헤더로 받은 Access 토큰과 Refresh 토큰
@Setter
대신 super()
의 생성자를 이용하는 쪽으로 해결 보았다.class AccountDetailService implements UserDetailsService
의private final class AccountDetails
...(전략)
@AllArgsConstructor
private final class AccountDetails extends Account implements UserDetails {
public AccountDetails(Account account) {
super(account.getAccountId(), account.getEmail(), account.getPassword(), account.getRoles(), account.getDisplayName());
}
}
...후략
유익한 자료 감사합니다.