Почему эта реализация Spring Security проверяет только пароль, а не имя пользователя?

#java #spring-boot #authentication #spring-security

#java #spring-boot #аутентификация #spring-безопасность

Вопрос:

Я работаю над простым приложением Spring Boot с использованием Spring Security. И я жестко ввел имя пользователя и пароль, но проблема в том, что я могу войти в систему с любым именем пользователя, только пароль проверяется Spring Security.

Это код:

 @EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    public final MyUserDetailsService userDetailsService;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService);
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}
  

Класс MyUserDetailsService:

 @Service
public class MyUserDetailsService implements UserDetailsService {

    private static final String USERNAME = "john";
    private static final String PASSWORD = "$2a$10$5yPLXyd0J2TEHhsbD3Azjumpn6OePKsiV1XPpFaZfytT33mRAn3N6";

    @Override
    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
        return new org.springframework.security.core.userdetails
                .User(USERNAME, PASSWORD, new ArrayList<>());
    }
}
  

Класс контроллера Rest:

 @RestController
public class ApiController {

    @GetMapping("/hello")
    public String sendMoney() {
        return "Hello World!";
    }
}
  

Я жестко запрограммировал имя пользователя «john» и пароль «test», зашифрованные с помощью BCrypt. Но проблема в том, что я могу войти в систему под любым именем пользователя, только пароль должен быть «тестовый». Может кто-нибудь объяснить мне, почему? Почему Spring Security проверяет только пароль на «тест», но не проверяет, является ли имя пользователя «john»? Любая обратная связь будет оценена. Спасибо!

Ответ №1:

Это сделано специально. UserDetailsService.loadUserByUsername(String user) ожидается, что будет предоставлена запись, соответствующая user . Допустимо использовать жестко закодированную запись, но тогда вы несете ответственность за правильность имени пользователя.

Но на самом деле, если вы хотите, чтобы SpringSecurity проверял как имя пользователя, так и пароль, вам не следует внедрять пользовательский UserDetailService , а напрямую использовать a InMemoryUserDetailsManager , который предоставляет его из коробки.

Ответ №2:

Кажется, вы игнорируете аргумент s :

     public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
  

другими словами, для любых пользовательских данных, которые запрашивается у кода, он извлекает жестко запрограммированные. Пользователь «notjohn»? Конечно, у нас это есть. Пользователь «не существует»? У нас тоже есть и т. Д.

Я предполагаю, что ваше намерение состоит в том, чтобы проверить, s равно ли "john" и возвращает жестко заданные данные пользователя, только если запрошенное имя пользователя "john" .