Почему Spring SAML препятствует работе Spring OAuth2?

Я добавляю Spring SAML в некоторые программы, которые до сих пор использовали только OAuth2. Мне нужно убедиться, что OAuth по-прежнему работает, поскольку SAML доступен только для некоторых наших клиентов.

Я столкнулся с проблемой, когда старый oAuth, кажется, больше не работает (хотя SAML в основном в порядке). Кажется, что диспетчер аутентификации как-то перезаписывается, но непонятно, как и почему. Вот соответствующий код в моем WebSecurityConfig.java:

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(userDetailsService)
            .passwordEncoder(passwordService.getEncoder())
            .and()
            .authenticationProvider(samlAuthenticationProvider)
            .authenticationProvider(oAuth2AuthenticationProvider());
}

И SAMLConfig.java:

@Bean
public SAMLProcessingFilter samlWebSSOProcessingFilter() throws Exception {
    SAMLProcessingFilter samlWebSSOProcessingFilter = new SAMLProcessingFilter();
    samlWebSSOProcessingFilter.setAuthenticationManager(authenticationManager());
    samlWebSSOProcessingFilter.setAuthenticationSuccessHandler(successRedirectHandler());
    samlWebSSOProcessingFilter.setAuthenticationFailureHandler(authenticationFailureHandler());
    return samlWebSSOProcessingFilter;
}

@Bean
public AuthenticationManager authenticationManager() {
    return new ProviderManager(Collections.singletonList(samlAuthenticationProvider()));
}

Очевидно, что это неправильно, но как исправить непонятно.

Когда я отлаживаю, AuthenticationManagerBuilder.performBuild () вызывается три раза при запуске.

  • Первый раз создает один с SAML, OAuth2 и Dao AuthenticationProvider.
  • Второй создает один с AnonymousAuthenticationProvider.
  • Третий строит один с другим DaoAuthenticationProvider.

При входе в систему дважды вызывается ProviderManager.authenticate ().

  • Впервые у него есть только один провайдер - AnonymousAuthenticationProvider. Это не подтверждает подлинность.
  • Второй раз родительский менеджер в первый раз. У него только один провайдер - SAMLAuthenticationProvider. Если пользователь, с которым я выполняю аутентификацию, не найден в SAML, это все равно последний вызываемый провайдер или менеджер.

Почему? Как мне исправить это, чтобы я мог либо направить учетные данные в SAML в некоторых случаях и OAuth во всех других случаях, либо разрешить любым учетным данным, которые не работают в SAML, переполняться в OAuth?

Вы регистрируете глобальный AuthenticationManager с помощью метода authenticationManager. Вы не должны этого делать.

M. Deinum 02.05.2018 08:38

@ M.Deinum Хорошо. Не могли бы вы уточнить? Я следую нескольким примерам, которые это делают.

AlbeyAmakiir 02.05.2018 08:46

См. github.com/vdenotaris/spring-boot-security-saml-sample/blob/‌…. Ваш SAMLConfig также должен расширять WebSecurityCOnfiger или, что еще лучше, вы хотите поместить его в один WebSecurityConfig, чтобы вы могли получить общий authenticationManager.

M. Deinum 02.05.2018 08:50

@ M.Deinum Хорошо. Что делает такой подход правильным? Часть моего вопроса включала «почему», поскольку я предпочитаю понимать, а не слепо следовать. Может, это ответ?

AlbeyAmakiir 02.05.2018 09:02

Почему это мой первый комментарий. Вы предоставляете свой собственный глобальный менеджер аутентификации, который содержит только поставщика аутентификации SAML, что в основном делает ваш configure из AuthenticationManagerBuilder бесполезным.

M. Deinum 02.05.2018 10:20

@ M.Deinum А, понятно. Почему бы не опубликовать более полный ответ, а не фрагментарный в комментариях?

AlbeyAmakiir 03.05.2018 01:57

@AlbeyAmakiir Я пытаюсь добиться подобного. У вас есть ссылка на git, где я мог бы сослаться на то, чего вы достигли, и как вы это решили.

truekiller 11.06.2019 08:43
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
7
267
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

new ProviderManager() создает AuthenticationManager, который пропускает процесс компоновки, поэтому он не отображается при отладке performBuild().

Метод bean-компонента authenticationManager() предназначен для возврата существующего глобального AuthenticationManager, но способ его использования в вопросе вместо этого возвращает новый и другой AuthenticationManager, перезаписывая то, что возвращает построитель. Вот почему делает отображается при отладке authenticate(), а встроенный AuthenticationManager - нет.

Решение состоит в том, чтобы передать существующий AuthenticationManager на SAMLProcessingFilter.setAuthenticationManager(), а не новый. Я сделал это следующим образом: переместил весь код из SAMLConfig.java в WebSecurityConfig.java, что было проще, но это не единственный способ сделать это.

Столкнулся с очень похожей проблемой. Можете поделиться конфигурацией?

truekiller 01.07.2019 13:09

Другие вопросы по теме