728x90
기본적으로 Spring Security에서 사용자 인증을 처리하기 위해 UserDetailsService 인터페이스를 제공한다.
근데 실습을 진행하면서 두가지 방법으로 구현하는 게 있어서 차이가 뭔가 해서 정리하기로 했다.
1. 메모리를 사용한 사용자 인증 방법 - 1
@Bean
public UserDetailsService userDetailsService() {
UserDetails user = User.withUsername("user")
.password(passwordEncoder().encode("1234"))
.roles("USER")
.build();
UserDetails admin = User.withUsername("admin")
.password(passwordEncoder().encode("1234"))
.roles("ADMIN")
.build();
UserDetails superuser = User.withUsername("superuser")
.password(passwordEncoder().encode("1234"))
.roles("SUPERUSER")
.build();
UserDetails ks = User.withUsername("ks")
.password(passwordEncoder().encode("1234"))
.roles("ADMIN", "USER")
.build();
return new InMemoryUserDetailsManager(user, admin, superuser, ks); // UserDetails 추가 필수
}
- 저장소 : 메모리에 사용자 정보를 저장한다.
- 애플리케이션 재시작 시 사용자 정보가 초기화된다.
- InMemoryUserDetailsManager를 사용하여 사용자를 저장한다.
- User.withUsername, password, roles 메서드를 사용하여 사용자 정보를 설정한다.
- passwordEncoder().encode("1234")를 사용하여 비밀번호를 암호화한다.
- 테스트나 데모용으로 메모리에 사용자 정보를 저장하는 방식이다. 프로젝트 초기에 하면 좋을듯
2. 데이터베이스를 사용한 사용자 인증 방법 - 2
@Service
@RequiredArgsConstructor
public class CustomUserDetailsService implements UserDetailsService {
private final UserRepository userRepository;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findByUsername(username); // 데이터베이스에서 사용자 이름을 기준으로 사용자를 조회
if(user == null){
throw new UsernameNotFoundException("사용자가 없습니다.");
}
// UserBuilder를 사용하여 UserDetails 객체를 생성
// withUsername(username)를 호출하여 사용자 이름을 설정
UserBuilder userBuilder = org.springframework.security.core.userdetails.User.withUsername(username);
userBuilder.password(user.getPassword()); // 암호화된 비밀번호를 설정
userBuilder.roles(user.getRoles().stream().map(role -> role.getName()).toArray(String[]::new));
return userBuilder.build(); // 완성된 UserDetails 객체를 반환
}
}
- 저장소 : 데이터베이스에서 사용자의 정보를 조회한다.
- 사용자 정보의 변경, 추가, 삭제가 데이터베이스에서 이루어진다.
- 사용자가 직접 만든 UserRepository를 사용하여 사용자 정보(데이터)를 가져온다.
- UserBuilder를 사용하여 UserDetails 객체를 생성합니다.
두 번재 방식을 풀이 하자면,
UserDetailsService 인터페이스는 기본적으로 사용자 이름을 통해 사용자를 로드하는 기능을 제공한다.
UserDetailsService 의 메서드 중 loadUserByUsername 메서드는 데이터베이스에서 주어진 사용자 이름(username)을 기반으로 사용자의 세부 정보를 검색하고 반환하는 역할을 하는 메서드이다.
- UserBuilder를 사용하여 UserDetails 객체를 생성한다.
- withUsername(username)를 호출하여 사용자 이름을 설정한다.
- password(user.getPassword())를 호출하여 암호화된 비밀번호를 설정한다.
- roles(user.getRoles().stream().map(role -> role.getName()).toArray(String[]::new))를 호출하여 사용자의 역할을 설정한다.
- 이 과정에서 사용자의 역할을 문자열 배열로 변환한다.
- loadUserByUsername 메서드를 통해 데이터베이스에서 사용자를 조회하고, UserDetails 객체로 변환하여 Spring Security가 이를 사용하여 인증을 처리할 수 있도록 한다.
결론:
두 방법 모두 UserDetailsService 인터페이스를 구현하여 사용자 인증을 처리하지만, 실제 애플리케이션에서는 두 번째 방법처럼 데이터베이스를 사용하는 방법이 더 일반적이다.
즉 첫 번째 방법은 주로 개발 초기 단계나 테스트 환경에서 유용하게 사용된다.
---> 2번재 방법을 사용하자!
728x90