[Spring] UserDetailsService, PasswordEncoder 재정의

노유성·2023년 7월 31일
0
post-thumbnail

UserDetailsService 재정의

사용자의 정보를 조회하는 역할을 하는 UserDetailsService는 재정의를 하는 방법이 2가지가 있다. 하나는 Spring Security에 있는 정의를 사용하는 것, 하나는 직접 구현을 하는 것이다.

InMemoryUserDetailsManager

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를 새로운 빈으로 등록해서 기본 구성을 재정의할 수 있다. 하지만 이렇게 구성하면 문제가 있다.

  1. 사용자가 없다.(기존에는 boot가 생성해줌)
  2. PasswordEncoder가 없다.

UserDetailsService를 재정의하면 당연하게도 PasswordEncoder를 재정의해주어야 한다. 그래서 이 점을 해결하기 위해 작업이 필요하다.

  1. 사용자를 만든다.
  2. UserDetailsService에 추가한다.
  3. 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이다. 학습 목적으로 해싱을 신경쓰지 않고 공부하기 위해 쓰인다.

결과

profile
풀스택개발자가되고싶습니다:)

2개의 댓글

comment-user-thumbnail
2023년 7월 31일

많은 도움이 되었습니다, 감사합니다.

1개의 답글