초기 에러 메시지는 이런식으로 나오는데 우리팀은 에러상황일 때 code, message만 보내주기로 했고 메시지도 따로 정한 상황이라 커스텀이 필요했다
InternalAuthenticationServiceException 을 던진다.
이 경우, UserDetailsService를 상속받은 클래스의 loadUserByUsername 메소드를 수정하면 된다(우리 프로젝트의 경우, PrincipalDetailsService를 수정)
public class PrincipalDetailsService implements UserDetailsService {
private final UserRepository userRepository;
@Override
@Transactional
public PrincipalDetails loadUserByUsername(String email){
User user = userRepository.findByEmail(email).orElseThrow(
() -> new NotJoinedUserException(ErrorMessage.USER_EMAIL_INCORRET)
);
return new PrincipalDetails(user);
}
}
BadCredentialException 을 던진다.
→ CustomAuthenticationProvider를 만들기
@RequiredArgsConstructor
@Log4j2
public class CustomAuthenticationProvider implements AuthenticationProvider {
private final UserDetailsService userDetailsService;
private final BCryptPasswordEncoder passwordEncoder;
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
UsernamePasswordAuthenticationToken token = (UsernamePasswordAuthenticationToken) authentication; // AuthenticaionFilter에서 생성된 토큰으로부터 아이디와 비밀번호를 조회함
String userEmail = token.getName();
String userPw = (String) token.getCredentials(); // UserDetailsService를 통해 DB에서 아이디로 사용자 조회
PrincipalDetails userDetailsVO = (PrincipalDetails) userDetailsService.loadUserByUsername(userEmail);
if (!passwordEncoder.matches(userPw, userDetailsVO.getPassword())) {
throw new NotJoinedUserException(ErrorMessage.USER_PASSWORD_INCORRET);
}
return new UsernamePasswordAuthenticationToken(userDetailsVO, userPw, userDetailsVO.getAuthorities());
}
@Override
public boolean supports(Class<?> authentication) {
return authentication.equals(UsernamePasswordAuthenticationToken.class);
}
}
→ SecurityConfig에도 빈으로 등록해준다
@EnableWebSecurity //해당 파일로 시큐리티를 활성화
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true) //@PreAuthorize 어노테이션을 메소드 단위로 추가하기 위해
@RequiredArgsConstructor
public class SecurityConfig extends WebSecurityConfigurerAdapter {
...
@Bean
public CustomAuthenticationProvider customAuthenticationProvider() {
return new CustomAuthenticationProvider(principalDetailsService, encode());
}
@Override
public void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
authenticationManagerBuilder
.authenticationProvider(customAuthenticationProvider());
}
...
}