Пул соединений LDAP с Spring Security

Я пытался настроить пул соединений LDAP, используя Spring Security и конфигурацию на основе xml.

Ниже моя конфигурация,

 <authentication-manager id="authenticationManager">
      <ldap-authentication-provider server-ref="ldapServer"
       user-dn-pattern="uid={0},ou=users"
       group-search-filter="(&amp;(objectClass=groupOfUniqueNames)(uniqueMember={0}))"
       group-search-base="ou=groups"
       group-role-attribute="cn"
       role-prefix="ROLE_"
       user-context-mapper-ref="ldapContextMapperImpl">
      </ldap-authentication-provider> 
 </authentication-manager>

Как предоставить всю конфигурацию пула соединений? Я собираюсь использовать класс PoolingContextSource, поскольку он предоставляет свойства для настройки размера пула и т. д.


person r_pawar    schedule 06.06.2016    source источник


Ответы (2)


Соединения в пуле не работают с аутентификацией, потому что аутентификация LDAP работает так, что подключение аутентифицируется при создании.

person marthursson    schedule 07.06.2016
comment
Если это так, то почему указаны DN и пароль менеджера? Насколько я понимаю, клиент подключается к серверу LDAP, используя dn менеджера и пароль, а затем отправляет запрос на привязку, который имеет dn пользователя и пароль, который используется для аутентификации. Таким образом, первоначальное соединение, созданное с использованием dn и пароля менеджера, не объединено в пул? - person r_pawar; 07.06.2016
comment
Также, как указано выше, в веб-приложении, если используется аутентификация на основе LDAP с помощью операции BIND, каждый пользователь, который входит в систему, создает свое собственное соединение ldap. Это приведет к множеству подключений ldap. Нет ли способа создать пул и повторно использовать для них соединения? Как мы можем установить время простоя или тайм-аут хотя бы для этих соединений? - person r_pawar; 07.06.2016
comment
Соединение, созданное для каждого отдельного пользователя, должно автоматически закрываться инфраструктурой Spring LDAP, так что вам не о чем беспокоиться. В дополнение к этому будет создано LDAP-соединение менеджера, которое будет использоваться для поиска пользователя перед аутентификацией. Это соединение также будет автоматически закрыто, и теоретически это должно быть возможным для пула, но, похоже, XML-код ldap-сервера не поддерживает это. Однако элемент ldap-server создает только экземпляр ContextSource, поэтому вы можете попробовать создать ‹ldap:context-source› и использовать его вместо этого. - person marthursson; 07.06.2016
comment
Как вы сказали, соединение с менеджером будет использоваться для поиска пользователя перед аутентификацией. После аутентификации пользователя извлекаются ли роли для пользователя с помощью подключения менеджера? Что делать, если у аутентифицированного пользователя нет разрешений на запрос своих ролей? Есть ли способ использовать подключение менеджера для запроса ролей аутентифицированного пользователя? в настоящее время используется тег «ldap-authentication-provider», я не видел такой опции. - person r_pawar; 07.06.2016

Они явно удалили объединение для привязок ldap (или, в случае Spring, authenticate):

https://github.com/spring-projects/spring-ldap/issues/ 216

ldapTemplate.authenticate ищет пользователя и вызывает contextSource.getContext для выполнения привязки ldap.

private AuthenticationStatus authenticate(Name base,
                            String filter,
                            String password,
                            SearchControls searchControls,
                            final AuthenticatedLdapEntryContextCallback callback,
                            final AuthenticationErrorCallback errorCallback) {

    List<LdapEntryIdentification> result = search(base, filter, searchControls, new LdapEntryIdentificationContextMapper());
    if (result.size() == 0) {
        String msg = "No results found for search, base: '" + base + "'; filter: '" + filter + "'.";
        LOG.info(msg);
        return AuthenticationStatus.EMPTYRESULT;
    } else if (result.size() > 1) {
        String msg = "base: '" + base + "'; filter: '" + filter + "'.";
        throw new IncorrectResultSizeDataAccessException(msg, 1, result.size());
    }

    final LdapEntryIdentification entryIdentification = result.get(0);

    try {
        DirContext ctx = contextSource.getContext(entryIdentification.getAbsoluteName().toString(), password);
        executeWithContext(new ContextExecutor<Object>() {
            public Object executeWithContext(DirContext ctx) throws javax.naming.NamingException {
                callback.executeWithContext(ctx, entryIdentification);
                return null;
            }
        }, ctx);
        return AuthenticationStatus.SUCCESS;
    }
    catch (Exception e) {
        LOG.debug("Authentication failed for entry with DN '" + entryIdentification.getAbsoluteName() + "'", e);
        errorCallback.execute(e);
        return AuthenticationStatus.UNDEFINED_FAILURE;
    }
}

По умолчанию источники контекста отключают объединение. От AbstractContextSource.java (от которого наследуется LdapContextSource):

public abstract class AbstractContextSource implements BaseLdapPathContextSource, InitializingBean {
...
    public DirContext getContext(String principal, String credentials) {
        // This method is typically called for authentication purposes, which means that we
        // should explicitly disable pooling in case passwords are changed (LDAP-183).
        return doGetContext(principal, credentials, EXPLICITLY_DISABLE_POOLING);
    }

    private DirContext doGetContext(String principal, String credentials, boolean explicitlyDisablePooling) {
      Hashtable<String, Object> env = getAuthenticatedEnv(principal, credentials);
      if(explicitlyDisablePooling) {
          env.remove(SUN_LDAP_POOLING_FLAG);
      }

      DirContext ctx = createContext(env);

      try {
          authenticationStrategy.processContextAfterCreation(ctx, principal, credentials);
          return ctx;
      }
      catch (NamingException e) {
          closeContext(ctx);
          throw LdapUtils.convertLdapException(e);
      }
  }
...
}

И если вы попытаетесь использовать PoolingContextSource, вы получите UnsupportedOperationException, когда authenticate попытается позвонить getContext:

public class PoolingContextSource
        extends DelegatingBaseLdapPathContextSourceSupport
        implements ContextSource, DisposableBean {

...
    @Override
    public DirContext getContext(String principal, String credentials) {
        throw new UnsupportedOperationException("Not supported for this implementation");
    }
}

Этот код взят из артефакта spring-ldap-core 2.3.1.RELEASE maven.

Вы по-прежнему можете создавать пулы соединений для поиска ldap с помощью PoolingContextSource, но пулы соединений для проверки подлинности работать не будут.

person trung    schedule 25.08.2017