스프링 시큐리티

Ch03. 실전프로젝트(인증 프로세스 Form 인증 구현) - DB 연동 인증 처리 CustomUserDetailsService

webmaster 2022. 1. 18. 17:14
728x90

CustomUserDetailsService(1)

  • UserDetails를 연동할 CustomService를 작성한다.

UserDetailsService를 구현

  • UserDetailsService를 구현한 내 커스텀 Class를 작성한다.
  • 내 DB에 있는 데이터를 읽어와야 하므로, 내 DB에 존재하는 UserRepository를 Autowire 한다.
  • loadUserByUsername을 구현해야 하는데, 이때, DB에서 값을 조회해 없으면 예외를 발생시킨다.
  • 값이 있다면, AccountContext에서 UserDetailsType을 반환하여 리턴한다.

AccountContext

UserDetails를 반환하는 AccontContext

  • 생성자로, 내 인증 객체인 account와 권한을 입력받는다.
  • 권한은 List와 같은 Collection으로 입력받는데.
  • 이러한 방식으로 권한을 입력할수 있다.

SecurityContext 수정

내 userDetailService를 주입한다.

  • 더 이상 제공되는 UserDetailsService를 주입하는 것이 아닌 내 userDetailsService를 주입한다.

CustomUserDetailsService(2)

  • CustomAuthenticationProvider를 작성하여 커스텀 인증을 할 수 있다.
    • 해당 Provider에서 UserDetailsService를 사용할 것이기 떄문에 이전에 UserDeailsService를 등록한 부분을 삭제하고 Provider만 넣으면 된다.

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(); //authentication에서 입력한 값을 가지고 올수 있다.
        AccountContext accountContext = (AccountContext)userDetailsService.loadUserByUsername(username);

        if(!passwordEncoder.matches(password, accountContext.getAccount().getPassword())){
            throw new BadCredentialsException("BadCredentialsException"); //패스워드 일치 X
        }

        UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken
                = new UsernamePasswordAuthenticationToken(accountContext.getAccount(), null, accountContext.getAuthorities());

        return usernamePasswordAuthenticationToken;
    }

    @Override
    public boolean supports(Class<?> authentication) {
        //UsernamePasswordAuthenticationToken 과 authentication 타입이 같다면 인증처리를 해라
        return UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication);
    }
}
  • AuthenticationProvider를 구현하여 작성할 수 있다.
    • 해당 Provider에서 UserDetailsService 를 Autowire 하여 사용한다.
    • providerManager가 사용할 Provider타입이 같은지를 찾으면서 있으면 해당 Provider를 사용하고, 없다면 부모 Provider를 검색한다.
    • 해당 Provider에서 suppports, authenticate를 구현한다. 
      • suppports
        • 해당 토큰이 같은지를 판단하여 인증을 성공할지를 판단하여 준다.
      • authenticate
        • ProviderManager가 사용할 Provider타입으로 선정이 되었을 경우 해당 메서드에서 인증처리를 한다.
        • 패스워드가 일치하지 않을경우 BadCredentialsException 이 발생한다.
        • 일치할 경우 해당 토큰을 반환하게 하여 Supports 메서드를 통과하게 한다(인증 성공)
728x90