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

+ Recent posts