使用spring security

时间:2016-06-06 15:50:42

标签: spring spring-security connection-pooling spring-ldap

我正在尝试使用spring security和基于xml的配置来设置LDAP连接池。

以下是我的配置

 <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类,因为它提供了配置池大小等的属性。

2 个答案:

答案 0 :(得分:1)

池化连接不适用于身份验证,因为LDAP身份验证的工作方式是在创建时对连接进行身份验证。

答案 1 :(得分:1)

他们明确删除了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.javaLdapContextSource继承自的内容):

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工件。

您仍然可以使用PoolingContextSource为ldap搜索执行连接池,但无法使用连接池进行身份验证。