24년도 웹프로젝트를 진행하다가 JWT에서 계속해서 Overflow에러가 발생하는것을 알아냈다.
AuthenticationManager문제라는데 아무리 찾아봐도 안나와서 이거 큰일났구만 하면서 구글을 계속 뒤져봤고 GPT에도 물어봤다.
그랬더니 이러한 문제점은 두개이상의 UserDetailsService가 존재할때 나타난다는 사실을 알게되었다. 그래서 이런 부분을 어떻게 해결해야하지 다시 구글을 뒤져보다가 나와 비슷한 문제를 겪는 사람을 깃허브에서 발견했다.
https://github.com/spring-projects/spring-framework/issues/29215
AopTestUtils.getUltimateTargetObject results in stack overflow for proxy backed by LazyInitTargetSource · Issue #29215 · sprin
Security configuration class @Configuration @EnableGlobalMethodSecurity(prePostEnabled = true) public class SecurityConf { @Bean public AuthenticationManager authenticationManagerBean(Authenticatio...
github.com
글을 쭉 내려보다가
@Bean
AuthenticationManager authenticationManager(UserDetailsService myUserDetailsService, PasswordEncoder encoder) {
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setUserDetailsService(myUserDetailsService);
provider.setPasswordEncoder(encoder);
return new ProviderManager(provider);
}
이런식으로 작성하면 문제가 해결될거같다는 의견을 봤고 이걸 그대로 실행해봤지만 문제가 해결되진 않았다. 그래서 어떻게해야하지~ 하고 고민을 하다 위 코드를 GPT에 넣고 돌려봤더니
"@Qualifier 또는 @Primary를 사용하여 어느 UserDetailsService를 사용할지 명확히 지정할 수 있습니다." 라는 답변을 받았고
@Qualifier("companyDetailsService")
@Qualifier("customUserDetailsService")
를 이용해 먼저 각 DetailsService를 정의해준 후 SpringSecurityConfig 내에서
@Qualifier("companyDetailsService")
private final UserDetailsService companyDetailsService;
@Qualifier("customUserDetailsService")
private final UserDetailsService customUserDetailsService;
이런식으로 매핑을 진행하게 해줬다. 그 후
@Bean
public DaoAuthenticationProvider companyAuthenticationProvider() {
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setUserDetailsService(companyDetailsService);
provider.setPasswordEncoder(passwordEncoder());
return provider;
}
@Bean
public DaoAuthenticationProvider customAuthenticationProvider() {
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setUserDetailsService(customUserDetailsService);
provider.setPasswordEncoder(passwordEncoder());
return provider;
}
@Bean
public AuthenticationManager authenticationManager() {
return new ProviderManager(List.of(companyAuthenticationProvider(), customAuthenticationProvider()));
}
위와같은 형태로 지정해준 각 DetailService들을 매니저에서 돌릴수 있게 코드를 작성해주니 잘 돌아가게 되었다.
전체 코드는 아래와 같다.
SecurityConfig.java
@Qualifier("companyDetailsService")
private final UserDetailsService companyDetailsService;
@Qualifier("customUserDetailsService")
private final UserDetailsService customUserDetailsService;
@Bean
public DaoAuthenticationProvider companyAuthenticationProvider() {
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setUserDetailsService(companyDetailsService);
provider.setPasswordEncoder(passwordEncoder());
return provider;
}
@Bean
public DaoAuthenticationProvider customAuthenticationProvider() {
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setUserDetailsService(customUserDetailsService);
provider.setPasswordEncoder(passwordEncoder());
return provider;
}
@Bean
public AuthenticationManager authenticationManager() {
return new ProviderManager(List.of(companyAuthenticationProvider(), customAuthenticationProvider()));
}
CompanyDetailsService.java
@Service
@Qualifier("companyDetailsService")
@RequiredArgsConstructor
public class CompanyDetailsService implements UserDetailsService { ...
CustomUserDetailsService.java
@Service
@Qualifier("customUserDetailsService")
@RequiredArgsConstructor
public class CustomUserDetailsService implements UserDetailsService {
'실력 향상 일지 > 자바' 카테고리의 다른 글
자바 파이썬 연동방법 (0) | 2024.06.16 |
---|---|
에러 : Springboot3 javax.servlet.http.HttpServletRequest (0) | 2024.05.27 |