반응형
이 포스트는 데어 프로그래밍님의 유튜브 강의를 듣고 나서 정리한 글입니다.
Adapter 패턴을 이용하여 UserDetails 구현
User 클래스는 UserDetails를 구현한 클래스입니다.
우리는 Adapter 패턴을 이용하여 User 클래스를 상속받을 것입니다.
public class AccountAdapter extends User {
private Account account;
public AccountAdapter(Account account) {
super(account.getUsername(), account.getPassword(), getAuthorities(account.getRoles()));
this.account = account;
}
public static Collection<? extends GrantedAuthority> getAuthorities(Set<AccountRole> accountRoles) {
return accountRoles.stream()
.map(r -> new SimpleGrantedAuthority("ROLE_" + r))
.collect(Collectors.toList());
}
}
UserDeatilsService 구현
@Service
public class AccountService implements UserDetailsService {
@Autowired
private AccountRepository accountRepository;
@Autowired
private PasswordEncoder passwordEncoder;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Account account = accountRepository.findByUsername(username)
.orElseThrow(() -> new NotFoundException("Not Found User By username : " + username));
return new AccountAdapter(account); // AccountAdapter는 User를 상속받았기 때문에 UserDetails 타입으로 사용 가능!
}
// ... Account 추가, 삭제, 수정 로직
}
UsernamePasswordAuthenticationFilter 구현
public class JwtAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
private AuthenticationManager authenticationManager;
public JwtAuthenticationFilter(AuthenticationManager authenticationManager) {
this.authenticationManager = authenticationManager;
}
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
// 로그인 인증을 할 때, UserDetailsService의 loadUserByUsername()이 호출이 된다.
}
}
- 스프링 시큐리티 필터에는 사용자 인증을 해주는 UsernamePasswordAuthenticationFilter가 있다.
- 기본적으로 POST "/login"으로 요청이 들어오면 해당 필터가 요청을 가로채서 인증을 합니다.
- 그 과정에서 attempAuthentication()는 UserDetailsService의 loadUserByUsername()을 호출합니다.
반응형