반응형
이번 포스트에서는 UserDetailsService, DTO 클래스를 작성해 보자
1. CustomUserDetailsService 코드 작성
1-1. 코드 작성하기
- 이 코드는 Spring Security의 사용자 인증 정보를 관리하는 UserDetailsService 인터페이스를 직접 커스텀해서 구현하여 사용자의 인증 정보를 로드하는 서비스를 정의하는 클래스다.
@Slf4j
@RequiredArgsConstructor
@Service
public class CustomUserDetailsService implements UserDetailsService {
private final UserRepository userRepository;
@Override
public UserDetails loadUserByUsername(String loginId) throws UsernameNotFoundException {
// 1. userRepository로부터 loginId로 유저정보를 받아온다.
User byLoginId = userRepository.findByLoginId(loginId)
.orElseThrow(
() -> new ProfileApplicationException(ErrorCode.USER_NOT_FOUND)
);
// 2.user를 dto로 변환시켜준다.
UserDto userDto = UserDto.fromEntity(byLoginId);
// 3. 사용자 정보를 기반으로 SecurityUserDetailsDto 객체를 생성한다.
return new SecurityUserDetailsDto(
userDto,
Collections.singleton(new SimpleGrantedAuthority(
userDto.roleType().toString()
))
);
}
}
1-2. 코드 분석
- CustomUserDetailsService는 UserDetailsService 인터페이스를 구현한다. 이 인터페이스의 loadUserByUsername 메서드는 사용자의 이름(여기선 loginId)으로 사용자의 정보를 불러오는 역할을 한다. 코드에서는 우선 userRepository를 통해 loginId에 해당하는 사용자 정보를 데이터베이스에서 조회한다. 사용자가 존재하지 않으면 UsernameNotFoundException 대신 ProfileApplicationException을 발생시키고, 이는 ErrorCode.USER_NOT_FOUND를 사용해 구체적인 에러 상황을 설명한다.
- 찾아낸 사용자 정보(User)는 DTO(Data Transfer Object)인 UserDto로 변환되어, 데이터를 캡슐화하고, 필요한 정보만을 가지는 형태로 만들어진다. 마지막으로, SecurityUserDetailsDto 객체가 생성되는데, 이 객체는 스프링 시큐리티에서 사용자의 상세 정보를 담는 역할을 한다. 사용자의 권한도 SimpleGrantedAuthority를 통해 설정되는데, 여기서는 UserDto의 roleType을 사용해서 권한을 설정한다. 이렇게 구현된 CustomUserDetailsService는 스프링 시큐리티에서 사용자 정보를 불러오고, 인증 및 권한 부여 과정에서 중요한 역할을 한다.
2. SecurityUserDetailsDto 구현
2-1. 코드 작성하기
- SecurityUserDetailsDto 클래스는 스프링 시큐리티의 핵심 부분 중 하나로, 사용자의 인증 정보를 관리하는 데 사용되는 UserDetails 인터페이스를 구현한다. 이 클래스에서 주목해야 할 점은 어떻게 이 인터페이스의 메서드들이 사용자 정보를 다루는지에 대한 부분이다.
@Slf4j
@Getter
@AllArgsConstructor
public class SecurityUserDetailsDto implements UserDetails {
@Delegate
private UserDto userDto;
private Collection<? extends GrantedAuthority> authorities;
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return Collections.singletonList(new SimpleGrantedAuthority(userDto.roleType().toString()));
}
@Override
public String getPassword() {
return userDto.password();
}
@Override
public String getUsername() {
return userDto.loginId();
}
@Override
public boolean isAccountNonExpired() {
return false;
}
@Override
public boolean isAccountNonLocked() {
return false;
}
@Override
public boolean isCredentialsNonExpired() {
return false;
}
@Override
public boolean isEnabled() {
return false;
}
}
2-2. 코드 분석
- 이 코드에서 중요한 부분은 UserDto 필드와 authorities 필드다. UserDto는 사용자의 정보를 담고 있고, authorities는 해당 사용자에게 부여된 권한들을 나타낸다. 여기서 @Delegate 애노테이션의 사용은 특히 눈에 띄는데, 이를 통해 UserDto의 메서드들을 SecurityUserDetailsDto에서 바로 호출할 수 있게 해, 코드를 더욱 간결하게 만들어준다.
- UserDetails 인터페이스를 구현한 메서드들을 보면, getAuthorities() 메서드는 사용자의 권한을 SimpleGrantedAuthority 객체로 변환하여 반환해 주는 역할을 한다. 이렇게 함으로써 스프링 시큐리티가 이해할 수 있는 형식으로 사용자의 권한을 제공하게 된다.
- getPassword()와 getUsername() 메서드는 각각 사용자의 비밀번호와 로그인 ID를 반환해주는데, 이는 UserDto에서 직접 가져오는 방식으로 구현되어 있다. 이로써 로그인 과정에서 필요한 기본적인 사용자 정보를 제공하게 된다.
- 마지막으로, isAccountNonExpired(), isAccountNonLocked(), isCredentialsNonExpired(), isEnabled()와 같은 메서드들은 계정의 상태를 나타내는데, 현재 예제에서는 모두 false로 설정되어 있어서, 실제 애플리케이션에서는 이 부분을 실제 상황에 맞게 조정해야 할 필요가 있다. 이 메서드들은 계정이 만료되었거나 잠겨 있거나, 그 밖의 상태를 나타내는 데 사용된다.
종합적으로, SecurityUserDetailsDto 클래스는 사용자의 인증 정보를 스프링 시큐리티가 이해할 수 있는 방식으로 제공하는 역할을 하고 있다.
다음 포스트에서 로그인과 메인페이지 컨트롤러를 생성하자👇🏻👇🏻
반응형
'Spring > Spring Security' 카테고리의 다른 글
Spring Boot 3.1 & Spring Security 6: 로그인 프로세스 및 JWT 토큰 동작 설명 (10편) (0) | 2023.08.08 |
---|---|
Spring Boot 3.1 & Spring Security 6: 로그인 & 메인 페이지 컨트롤러 (9편) (0) | 2023.08.08 |
Spring Boot 3 & Security 6 시리즈: JWT Util 클래스 작성 (7편) (0) | 2023.08.07 |
Spring Boot 3 & Security 6 시리즈: JWT 검증 인터셉터 작성하기 (6편) (0) | 2023.08.07 |
Spring Boot 3 & Security 6 시리즈: AuthenticationProvider, 인증 핸들러 구현하기 (5편) (0) | 2023.08.07 |