모르지 않다는 것은 아는것과 다르다.

Spring Security

CustomAuthenticationProvider

채마스 2022. 2. 28. 20:33

개요

  • 사용자의 이름과 패스워드를 받아서 검증해서 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

  • 정수원님의 스프링 시큐리티