Используйте другой AuthenticationProvider в зависимости от имени пользователя и удаленного IP-адреса

В приложении на основе Spring Security 3.2 мне нужно аутентифицировать пользователей от двух разных провайдеров на основе определенного шаблона в их имени пользователя и их удаленном IP-адресе.

Если они соответствуют определенным правилам, их следует аутентифицировать по ActiveDirectoryLdapAuthenticationProvider, в противном случае — по стандартному AuthenticationProvider с использованием уже существующей пользовательской реализации UserDetailsService.

Что мне нужно продлить? AuthenticationManager или AuthenticationProvider ? Любой пример кода будет высоко оценен :-)

Примечание. Я уже успешно пытался добавить два узла <authentication-provider /> в <authentication-manager />, и это сработало. Но меня беспокоит, что мой Ldap-сервер бьется при каждой попытке аутентификации (даже не предназначенной для этого)


person yglodt    schedule 27.01.2014    source источник


Ответы (1)


Вы можете создать оболочку, которая проверяет шаблон/IP-адрес, если он соответствует вызовам делегата, иначе возвращает значение null.

public class FilteringAuthenticationProvider implements AuthenticationProvider {
    private final AuthenticationProvider delegate;

    public FilteringAuthenticationProvider(AuthenticationProvider delegate) { this.delegate=delegate;}

    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        Object details = authentication.getDetails();
        String username = authentication.getPrincipal().toString();
        String remoteAddress = null;
        if (details instanceof WebAuthenticationDetails) {
            remoteAddress = ((WebAuthenticationDetails) details).getRemoteAddress(); 
        }

        if (matches(remoteAddress, username)) {
            return delegate.authenticate(authentication);
        }
        return null
    }

    private boolean matches(String remoteAddress, String Username) {
        // your checking logic here
    }       
}

Что-то вроде этого. Затем настройте его в своей конфигурации безопасности и дайте ему обернуть файл ActiveDirectoryLdapAuthenticationProvider.

<sec:authentication-manager>
    <sec:authentication-provider ref="filteringLdapProvider" />
    <sec:authentication-provider>
        <user-service ref="customUserDetailsService" />
    </sec:authentication-provider>
</sec:authentication-manager>

<bean id="filteringLdapProvider" class="FilteringAuthenticationProvider">
    <constructor-arg ref="ldapProvider" />
</bean>

<bean id="ldapProvider" class="ActiveDirectoryLdapAuthenticationProvider">
...
</bean>

Что-то вроде этого.

person M. Deinum    schedule 27.01.2014
comment
Правильно ли я понимаю, что delegate.authenticate(authentication) будет эффективно использовать мою реализацию UserDetailsService? А если matches(remoteAddress, username) == false я создаю экземпляр ActiveDirectoryLdapAuthenticationProvider и передаю ему authentication ? - person yglodt; 29.01.2014
comment
Нет... Как я уже говорил, вы просто оборачиваете свой ActiveDirectoryLdapAuthenticationProvider этим. На самом деле он будет вызывать ActiveDirectoryLdapAuthenticationProvider только в том случае, если совпадение истинно, иначе он возвращает null, который является триггером Spring Security для вызова следующего AuthenticationProvider в цепочке. - person M. Deinum; 29.01.2014
comment
См. измененный ответ. - person M. Deinum; 29.01.2014
comment
Спасибо за дополнительные подробности! - person yglodt; 31.01.2014