개요
- 사용자의 이름과 패스워드를 받아서 검증해서 AuthenticationManager 에게 전달하는 AuthenticationProvider 를 커스텀 해서 구현해 보려고 한다.
AuthenticationProvider
- 위와 같이 UserDetailService 로 부터 UserDetails 객체를 전달받아 검증하고 그 결과를 다시 AuthenticationManger 에게 전달한다.
코드
- CustomAuthenticationProvider 클래스 구현
public class CustomAuthenticationProvider implements AuthenticationProvider {
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private PasswordEncoder passwordEncoder;
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
String username = authentication.getName();
String password = (String)authentication.getCredentials();
AccountContext accountContext = (AccountContext)userDetailsService.loadUserByUsername(username);
if(!passwordEncoder.matches(password, accountContext.getAccount().getPassword())){
throw new BadCredentialsException("BadCredentialsException");
}
//String secretKey = ((FormWebAuthenticationDetails) authentication.getDetails()).getSecretKey();
//if (secretKey == null || !secretKey.equals("secret")) {
// throw new InsufficientAuthenticationException("Invalid Secret");
//}
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(accountContext.getAccount(),null,accountContext.getAuthorities());
return authenticationToken;
}
@Override
public boolean supports(Class<?> authentication) {
return UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication);
}
}
- authenticate, supports 메소드를 재정의한다.
- authenticate : 검증을 처리한다.
- supports : 인자로 받는 authentication 타입과 CustomAuthenticationProvider 가 사용하고자 하는 토큰의 타입이 일치하는지 검사한다.
- AccountContext 타입으로 변환해준다. (UserDetails -> AccountContext)
- 사용자가 입력한 password 와 디비에 저장된 password 가 같은지 검증하고, 다르다면 BadCredentialsException 를 던진다.
- 마지막으로 UsernamePasswordAuthenticationToken 으로 만들어서 반환해 준다.
SecurityConfig 에 CustomAuthenticationProvider 등록
@Configuration
@EnableWebSecurity
@Slf4j
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authenticationProvider());
}
@Bean
public AuthenticationProvider authenticationProvider() {
return new CustomAuthenticationProvider();
}
}
- 먼저 CustomAuthenticationProvider 를 빈으로 등록하고, authenticationProvider 메소드에 인자로 넘겨 줌으로써, 스프링 시큐리티가 기본적으로 제공하는 AuthenticationProvider 를 사용하지 않고, 직접 만든 CustomAuthenticationProvider 를 사용할 수 있다.
REFERENCES
- 정수원님의 스프링 시큐리티
'Spring Security' 카테고리의 다른 글
UsernamePasswordAuthenticationFilter 커스텀 하기 (0) | 2022.02.28 |
---|---|
WebAuthenticationDetails 와 AuthenticationDetailsSource (0) | 2022.02.28 |
AuthenticationManager 와 AuthenticationProvider (0) | 2022.02.28 |
Security Config (0) | 2022.02.28 |
SecurityContextHolder 와 FilterChainProxy (0) | 2022.02.28 |