Spring Security несколько провайдеров аутентификации - PullRequest
1 голос
/ 02 февраля 2020

Я настроил пружинную защиту, используя:

@Configuration
@Import(SecurityProblemSupport.class)
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

   @Autowired
   private RestAuthenticationProvider authenticationProvider;

   @Autowired
   private CustomUserDetailService customUserDetailService;

   @Override
   protected void configure(AuthenticationManagerBuilder auth) throws Exception {

        auth.authenticationProvider(authenticationProvider);
        auth.userDetailsService(customUserDetailService);

        super.configure(auth);
    }

Все работает как положено. Поставщик аутентификации Rest - это Компонент, который реализует AuthenticationProvider:

@Component
public class RestAuthenticationProvider implements AuthenticationProvider  {

Проблема заключается в том, что, если я добавлю в путь к классу другой @Component, который расширяет AbstractUserDetailAuthenticationProvider, RestAuthenticationProvider больше не используется; Вместо этого Spring использует одного поставщика по умолчанию, используя UserDetailService, указанный в конфигурации. Нет других ссылок на этот CustomAuthenticationProvider. Это просто в одной упаковке. То же самое происходит, если я использую в конфигурации CustomProvider, а остальное помечено компонентом и больше не используется.

@Component // <- if I remove this, everything works fine. 
public class CustomUserAuthenticationProvider extends
   AbstractUserDetailsAuthenticationProvider {

Я хотел бы переключиться между AuthenticationProvider (S) на основе некоторой конфигурации. Любая помощь приветствуется.

Ответы [ 3 ]

1 голос
/ 02 февраля 2020

Я бы предложил один AuthenticationProvider в вашем WebSecurityConfigurerAdapter с делегированным подходом, то есть реализовать только один поставщик аутентификации:

@Component
public class DelegatingAuthenticationProvider implements AuthenticationProvider  {

    private final AuthenticationProvider authenticationProviderFirstDelegate;

    private final AuthenticationProvider authenticationProvideSecondDelegate; // This uses your UserDetailsService, e.g.

    private final SomeProperty someProperty;

    public Authentication authenticate(Authentication authentication) {
        // Here based on someProperty, return authenticationProviderFirstDelegate.authenticate(authentication) or authenticationProviderSecondDelegate.authenticate(authentication)
    }
}

и потерять auth.userDetailsService(customUserDetailService);

1 голос
/ 02 февраля 2020

Вы можете добавить аннотацию ConditionalOnProperty к бобу.

Spring будет включать этот компонент в контекст, только если условие включено или имеет заданное значение c.

Для вашего кода это будет выглядеть следующим образом:

@ConditionalOnProperty(name = "authprovider", havingValue = "custom")
public class CustomUserAuthenticationProvider extends
    AbstractUserDetailsAuthenticationProvider {

И в файле свойств (или соответствующем PropertySource) добавить authprovider свойство:

authprovider=custom

Другой вариант - добавить аннотацию @Profile к компоненту. Он отображает бин, отображающий этот конкретный профиль приложения. Я использую эту опцию для загрузки определенной конфигурации для конкретной среды разработки c. Я бы предложил использовать первый вариант в вашем случае.

0 голосов
/ 12 февраля 2020

Я решил эту проблему после нескольких попыток. Мне пришлось использовать

@Component
@ConditionalOnProperty(name = "authprovider", havingValue = "custom")
public class CustomUserAuthenticationProvider extends
    AbstractUserDetailsAuthenticationProvider {

и

@Component
@ConditionalOnProperty(name = "authentication.type", havingValue = "restCall")
public class RestAuthenticationProvider implements AuthenticationProvider  {

На двух компонентах.

Использование одного из двух непосредственно в методе "configure" WebSecurityConfigurerAdapter вызывал проблемы, так как весной по умолчанию автоматически использовался «провайдер».

Так что мне пришлось читать окружение и использовать ручную инъекцию боба:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

@Autowired
private Environment env;

// .....

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {

    if (env.getProperty("authentication.type").equals("standard")) {

    auth.authenticationProvider(applicationContext.getBean( 
      CustomUserAuthenticationProvider.class));
     } 

    else {

    auth.authenticationProvider(applicationContext.getBean(
      RestAuthenticationProvider.class));
    }

    auth.userDetailsService(customUserDetailService);

    super.configure(auth);
}
...