사용자의 정보를 조회하는 역할을 하는 UserDetailsService는 재정의를 하는 방법이 2가지가 있다. 하나는 Spring Security에 있는 정의를 사용하는 것, 하나는 직접 구현을 하는 것이다.
Spring Security에서 제공하는 InMemoryUserDetailsManager class 는 엄밀히 말하면 UserDetialsManager를 재정의 한 것이다. UserDetailsManager는 UserDetailsService는 상속받고 있는데 UserDetailsService에서는 조회의 기능만 있는 한편, Manager는 CURD기능을 모두 정의하고 있다.
@Configuration
public class ProjectConfig {
@Bean
public UserDetailsService userDetailsService() {
var userDetailsService = new InMemoryUserDetailsManager();
return userDetailsService;
}
}
이렇게 UserDetailsService를 새로운 빈으로 등록해서 기본 구성을 재정의할 수 있다. 하지만 이렇게 구성하면 문제가 있다.
UserDetailsService를 재정의하면 당연하게도 PasswordEncoder를 재정의해주어야 한다. 그래서 이 점을 해결하기 위해 작업이 필요하다.
엄밀히 말하면 UserDetailsService는 사용자를 추가할 수 없지만 우리는 Manager을 사용하므로 CURD기능을 사용할 수 있다.
@Configuration
public class ProjectConfig {
@Bean
public UserDetailsService userDetailsService() {
var userDetailsService = new InMemoryUserDetailsManager();
var user = User.withUsername("John")
.password("12345")
.authorities("read").build();
userDetailsService.createUser(user);
return userDetailsService;
}
@Bean
public PasswordEncoder passwordEncoder() {
return NoOpPasswordEncoder.getInstance();
}
}
InMemoryUserDetailsManager를 살펴보면,
private final Map<String, MutableUserDetails> users = new HashMap<>();
라는 필드가 존재한다. 그리고
@Override
public void createUser(UserDetails user) {
Assert.isTrue(!userExists(user.getUsername()), "user should not exist");
this.users.put(user.getUsername().toLowerCase(), new MutableUser(user));
}
라는 함수도 존재한다. 그래서 Spring Security에서 제공하는 User class의 builder를 이용해서 User객체를 생성한 후에 등록할 수 있다.
PasswordEncoder는 NoOpPasswordEncoder class를 이용한다. 별다른 해싱 기능없이 평문으로 비밀번호를 처리하는 Spring Security 내장 class이다. 학습 목적으로 해싱을 신경쓰지 않고 공부하기 위해 쓰인다.
많은 도움이 되었습니다, 감사합니다.