1. 개요

Spring Security는 애플리케이션의 보안 및 인증 관리를 간편하게 해준다. 그 중 UserDetailsService는 사용자 정보를 조회하고, 이를 기반으로 UserDetails 객체를 생성하는 데 중요한 역할을 한다. 이번 포스팅에서는 Spring Security의 UserDetailsService와 UserDetails 구현 방법을 예시와 함께 설명한다.

 

 

2. UserDetailsService 구현

UserDetailsService는 Spring Security에서 사용자 정보를 가져오는 인터페이스이다. 이 인터페이스를 구현하여 데이터베이스에서 사용자의 인증 정보를 가져오도록 구성할 수 있다.

@Service
public class UserDetailsServiceImpl implements UserDetailsService {

    private final UserRepository userRepository;

    public UserDetailsServiceImpl(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userRepository.findByUsername(username)
                .orElseThrow(() -> new UsernameNotFoundException("Not Found " + username));

        return new UserDetailsImpl(user);
    }
}

이 코드에서는 UserRepository를 통해 username에 해당하는 사용자를 데이터베이스에서 조회하고, 해당 사용자가 존재하지 않을 경우 UsernameNotFoundException을 발생시킨다. 만약 사용자가 존재하면, 이를 바탕으로 UserDetailsImpl 객체를 반환한다.

 

 

3. UserDetails 구현

UserDetails는 Spring Security에서 사용자 정보를 담는 인터페이스이다. 이를 구현한 UserDetailsImpl 클래스는 사용자의 기본 정보(예: username, password, 권한 등)를 제공한다.

public class UserDetailsImpl implements UserDetails {

    private final User user;

    public UserDetailsImpl(User user) {
        this.user = user;
    }

    public User getUser() {
        return user;
    }

    @Override
    public String getPassword() {
        return user.getPassword();
    }

    @Override
    public String getUsername() {
        return user.getUsername();
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        UserRoleEnum role = user.getRole();
        String authority = role.getAuthority();

        SimpleGrantedAuthority simpleGrantedAuthority = new SimpleGrantedAuthority(authority);
        Collection<GrantedAuthority> authorities = new ArrayList<>();
        authorities.add(simpleGrantedAuthority);

        return authorities;
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return true;
    }
}

위 코드에서 사용자의 권한을 GrantedAuthority 리스트로 반환하고 있으며, 이 리스트는 Spring Security에서 사용자의 권한을 관리하는데 사용된다.

 

 

4. @AuthenticationPrincipal 사용 예시

컨트롤러에서는 인증된 사용자의 정보를 받아서 사용할 수 있다. Spring Security에서는 @AuthenticationPrincipal 어노테이션을 통해 현재 인증된 사용자의 정보를 주입받을 수 있다.

@GetMapping("/products")
public String getProducts(@AuthenticationPrincipal UserDetailsImpl userDetails) {
    User user = userDetails.getUser();
    System.out.println("user.getUsername() = " + user.getUsername());
    return "redirect:/";
}

이 코드에서 UserDetailsImpl 객체를 통해 현재 인증된 사용자의 정보를 가져올 수 있으며, 이를 바탕으로 추가적인 작업을 수행할 수 있다.

 

 

5. 결론

Spring Security에서 사용자 인증 정보를 처리하는 UserDetailsService와 UserDetails의 구현은 필수적인 작업이다. 이를 통해 애플리케이션은 사용자에 대한 인증 및 권한 관리 작업을 손쉽게 수행할 수 있다. 이번 포스팅에서는 이를 실제 코드 예시와 함께 설명하였으며, 이를 활용하여 보안이 강화된 애플리케이션을 개발할 수 있다.