Spring Безопасность Пользовательская аутентификация - AuthenticationProvider vs UserDetailsService

Насколько я могу понять, когда вы хотите выполнить специальную проверку подлинности в Spring Security, вы можете либо реализовать пользовательский AuthenticationProvider или пользовательский UserDetailsService.

@Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth    
            //.authenticationProvider(authProvider)  // option 1
            .userDetailsService(userDetailsService); // option 2

    }

В AuthenticationProvider вы можете проверить имя пользователя и пароль и вернуть Authentication своим пользовательским объектом.

public Authentication authenticate(Authentication authentication){
        if (checkUsernameAndPassword(authentication)) {
            CustomUserDetails userDetails = new CustomUserDetails();
            //add whatever you want to the custom user details object
            return new UsernamePasswordAuthenticationToken(userDetails, password, grantedAuths);
        } else {
            throw new BadCredentialsException("Unable to auth against third party systems");
        }
    }

В UserDetailsService вы получаете только имя пользователя и когда вы возвращаете пользовательские UserDeatails, фреймворк выполняет проверку пароля.

public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        CustomUserDetails user = new CustomUserDetails();
        //add whatever you want to the custom user details object
        return user;
    }

Похоже, что обе могут давать похожие результаты. Итак, вопрос в чем разница? Когда пользователь один против другого?

Ответы

Ответ 1

Ответ внутри вашего вопроса. когда вы используете другую систему аутентификации, а пароль не указан в вашей собственной базе данных/модели данных, вы должны использовать AuthenticationProvider. например, я работал в проекте, что у клиента была централизованная система аутентификации (CAS), поэтому моя система не знала о пароле, мне пришлось реализовать AuthenticationProvider и отправить данный пароль в CAS и действовать согласно к его ответу.

Но в другой системе я сохранял пароль в своей базе данных, поэтому все, что мне нужно было сделать, это реализовать UserDetailsService и проверить, существует ли пользователь в моей базе данных или нет, spring -security должен был сделать все остальное.

Ответ 2

Эти два связаны друг с другом, но намеренно разделяются Spring Security. Если у предприятия есть несколько систем, UserDetailsService предоставит конкретную информацию пользователя, хранящуюся в вашей конкретной системе, даже если аутентификация МОЖЕТ быть выполнена совершенно другой системой. В простой системе их можно комбинировать. Например, вызов базы данных проверяет имя пользователя/пароль и извлекает все эти электронные письма, идентификатор и т.д.

Согласно Spring Справочник по безопасности: http://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#getting-started

Часто возникает проблема с UserDetailsService. Это чисто DAO для пользовательских данных и не выполняет никакой другой функции, кроме предоставления этих данных другим компонентам в рамках. В частности, он не аутентифицирует пользователя, который выполняется AuthenticationManager. Во многих случаях имеет смысл внедрить AuthenticationProvider напрямую, если вам нужен пользовательский процесс проверки подлинности.

Ответ 3

Из spring документации безопасности, https://docs.spring.io/spring-security/site/docs/5.0.0.RC1/reference/htmlsingle/#overall-architecture

Часто возникает проблема с UserDetailsService. Это чисто DAO для пользовательских данных и не выполняет никакой другой функции, кроме предоставления этих данных другим компонентам в рамках. В частности, он не аутентифицирует пользователя, который выполняется AuthenticationManager. Во многих случаях имеет смысл внедрить AuthenticationProvider напрямую, если вам нужен пользовательский процесс проверки подлинности.

AuthenticationProvider и UserDetailsService имеют другую цель.

АутентификацияProvider аутентифицирует (сравнивает) пользователя (запроса), предоставленного пользователю и паролю для пользователя системы (это может быть любая система, такая как БД, которая ведет список зарегистрированных пользователей)

Ответственность за выполнение UserDetailsService Реализация позволяет получить информацию о пользователе системы, которая соответствует пользователю, указанному пользователем. Здесь он просто получает пользователей, имеющих одинаковое имя пользователя, и не сообщает приложению, является ли проверка подлинности успешной или неудачной.

Пример: Spring предоставляет следующую настройку для аутентификации данных пользователя в базе данных по умолчанию

  • АутентификацияProvider - DaoAuthenticationProvider  который расширяет AbstractUserDetailsAuthenticationProvider, который вызывает метод аутентификации, передавая имя пользователя, объект аутентификации
  • UserDetailsService - JdbcDaoImpl
  • Поток аутентификации
  • Ответственность DaoAuthenticationProvider заключается в том, чтобы аутентифицировать имя пользователя и пароль, полученные из запроса, с помощью пользователя базы данных.
  • Чтобы получить соответствующего пользователя базы данных, он запрашивает UserDetailsService Implementataion JdbcDaoImpl, чтобы получить объект UserDetail из базы данных с именем, аналогичным запросу username.Here JdbcDaoImpl просто извлекает объект UserDetails из системы. Он либо отправит обратно пользователя, найденного в БД, либо отправить исключение, что пользователь не найден.
  • Если данные пользователя находятся в БД, DaoAuthenticationProvider затем проверяет пароль пользователя с запросом пароля, а пароль администратора еще не завершает проверку подлинности.
  • DaoAuthenticationProvider ответит, аутентифицирован ли пользователь или нет на основе ответа JdbcDaoImpl.

Посмотрите здесь, чтобы лучше понять:

AuthenticationProvider - DaoAuthenticationProviderextends AbstractUserDetailsAuthenticationProvider

UserDetailsService - JdbcDaoImpl

UserDetails - User