요약)
UserDetailsService 는 다중 구현체를 사용할 수 없으며 @Componenet 가 2개 이상 등록되면
AuthenticationManager.getObject() is null 에러가 뜹니다.
1개의 UserDetailsService 내에서 테이블 구분 메서드를 만들어서 해결하면 됩니다.
9월 18일 토이 프로젝트를 진행하던 중
Member , Market 테이블의 Mock 테스트를 완료한 후
JWT 를 이용하여 로그인을 구현하려고하였다.
UserDetailsService 를 2중 구현하여 SecurityConfig에서 AuthenticationManagerBuilder 설정으로 관리할 수 있을 것으로 생각하여 UserDetailsService 구현체를 2개를 만든 후 SecurityConfig 를 2개를 만들어
@Order , @Qualifier, @Primary 등 여러 설정을 반복하여 보며
스프링 시큐리티 구조를 계속 검색하여보았다. 독학이기에 구글링 , 스택오버플로우 , 오키 등 10일간 검색을 하였다.
websecurityconfigureradapter 인터페이스의 deprecated 해결 방법도 덕분에 알게되었다.
내린 결론은 UserDetailsService를 2개 이상 Componenet 등록하였을 시 마주한 Authentication.object is null 에러 또한
스프링이 UserDetailsService 의 구현체를 의존성 주입하지 못하기 때문에 일어난 일인 것을 깨닳았고
정말... 간단한 방법으로 10일간의 눈물흘리며 내 길이 아닌가까지 생각한 문제가 해결이 되었다.
이번 계기를 통해 느낀 점은 역시 안되는 것은 없다는 것이었다. 스트레스를 엄청 받았지만 해결하니 너무 뿌듯하였다.
아래는 코드입니다.
package hyeong.backend.domain.auth.details;
import hyeong.backend.domain.market.entity.persist.Market;
import hyeong.backend.domain.market.entity.vo.MarketEmail;
import hyeong.backend.domain.market.repository.MarketRepository;
import hyeong.backend.domain.member.Repository.MemberRepository;
import hyeong.backend.domain.member.entity.persist.Member;
import hyeong.backend.domain.member.entity.vo.MemberEmail;
import hyeong.backend.domain.member.exceptions.MemberNotFoundException;
import hyeong.backend.global.errors.exceptions.ErrorCode;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import java.util.Collections;
import java.util.Optional;
@Slf4j
@Component
@RequiredArgsConstructor
public class CustomUserDetailsService implements UserDetailsService {
private final MemberRepository memberRepository;
private final MarketRepository marketRepository;
@Override
@Transactional
public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
// 삼항 연산자 사용
// marketRepository (마켓 회원 값이 있을 경우) ?
// market/Repository 에서 회원을 찾은 후
// map 을 이용 아래 구현한 메서드 실행 회원이 없으면 예외 발생 :
// member Repository 에서 위와 동일하게 수행
return !marketRepository.findByEmail(MarketEmail.from(email)).isEmpty() ? marketRepository.findByEmail(MarketEmail.from(email))
.map(this::createdUserDetailsMarket)
.orElseThrow(() -> new MarketNotFoundException((ErrorCode.MARKET_NOT_FOUND))) : memberRepository.findByEmail(MemberEmail.from(email))
.map(this::createdUserDetailsMember)
.orElseThrow(() -> new MemberNotFoundException((ErrorCode.MEMBER_NOT_FOUND)));
}
private UserDetails createdUserDetailsMember(Member member) {
GrantedAuthority grantedAuthority = new SimpleGrantedAuthority("ROLE_" + member.getRoleType());
return new User(member.getEmail().email(),
member.getPassword().password(),
Collections.singleton(grantedAuthority));
}
private UserDetails createdUserDetailsMarket(Market market) {
GrantedAuthority grantedAuthority = new SimpleGrantedAuthority("ROLE_" + market.getRoleType());
return new User(market.getEmail().email(),
market.getPassword().password(),
Collections.singleton(grantedAuthority));
}
}
'스프링' 카테고리의 다른 글
[스프링부트] Junit5 설정 에러 모음 (0) | 2022.10.26 |
---|