PartialResultException:未处理的继续引用;剩余名称''

PartialResultException: Unprocessed Continuation Reference(s); remaining name ''

我们目前正在更新我们的 LDAP 服务器。在以前的服务器中,我们使用匿名绑定。 这些是我们使用的旧属性:

url = ldap://urlexample.com/dc=company,dc=com
filter = (uid={0})
base = ou=People,ou=Corporate
dn =
password =

这些属性适用于以下 spring 安全配置 class:

/*Omitted imports to simplify*/

@Configuration
@EnableWebSecurity(debug = false)
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
    private static final Logger logger = LoggerFactory.getLogger(SecurityConfig.class);
    
    @Value("${base}")
    private String userSearchBase;
    
    @Value("${filter}")
    private String userSearchFilter;

    @Value("${url}")
    private String ldapUrl;

    @Value("${dn}")
    private String managerDn;

    @Value("${password}")
    private String managerPassword;

    private String performLoginUrl = "/perform_login";
    private String loginUrl = "/login";
    private String userNameParam = "username";
    private String passwordParam = "password";

    @Autowired
    private CustomLoginSuccessHandler customLoginSuccessHandler;
    
    @Autowired
    private CustomLoginFailureHandler customLoginFailureHandler;
    
    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.ldapAuthentication()
                .userSearchBase(userSearchBase)
                .userSearchFilter(userSearchFilter)
                .contextSource(contextSource());
    }
    
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        super.configure(http);

         // Some other code...

         // security:form-login
         http.formLogin()
                .loginPage(loginUrl)
                .loginProcessingUrl(performLoginUrl)
                .successHandler(customLoginSuccessHandler)
                .failureHandler(customLoginFailureHandler)
                .usernameParameter(userNameParam)
                .passwordParameter(passwordParam)
                .permitAll();

        // some other code...
    }
    
    @Override
    public void configure(WebSecurity web) throws Exception {
        super.configure(web);
        
        //some other code... 
    }
    
    @Bean
    public BaseLdapPathContextSource contextSource() {
        DefaultSpringSecurityContextSource ctxSource = new DefaultSpringSecurityContextSource(ldapUrl);     
        
        if(StringUtils.isNotBlank(managerDn)) {
            ctxSource.setUserDn(managerDn);
        }
        
        if(StringUtils.isNotBlank(managerPassword)) {
            ctxSource.setPassword(managerPassword);
        }
        
        // ctxSource.setAnonymousReadOnly(Boolean.TRUE);
        
        ctxSource.afterPropertiesSet();
        
        return ctxSource;
    }
    
    @Bean(name = "ldapTemplate", autowire = Autowire.BY_NAME)
    public LdapTemplate ldapTemplate() {
        return new LdapTemplate(contextSource());
    }
}

新 LDAP 的新属性如下:

url = ldaps://urlexample2/dc=corp,dc=company,dc=com
filter = (&(sAMAccountName={0})(objectclass=user))
base = OU=CorpUsers
dn= CN=ldap,OU=ServiceAccounts,DC=corp,DC=company,DC=com
password = pwdExample

有了这些信息,相同的代码现在 returns 在登录过程中出现 PartialResultException(我假设这是在登录过程中发生的,因为没有来自 successHandler 或 failureHandler 的日志出现)。在我输入我的凭据并单击“登录”表单按钮后出现以下异常:

org.springframework.ldap.PartialResultException: Unprocessed Continuation Reference(s); nested exception is javax.naming.PartialResultException: Unprocessed Continuation Reference(s); remaining name ''
    org.springframework.ldap.support.LdapUtils.convertLdapException(LdapUtils.java:216)
    org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:385)
    org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:328)
    org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:629)
    org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:570)
    org.springframework.security.ldap.SpringSecurityLdapTemplate.searchForMultipleAttributeValues(SpringSecurityLdapTemplate.java:241)
    org.springframework.security.ldap.SpringSecurityLdapTemplate.searchForSingleAttributeValues(SpringSecurityLdapTemplate.java:166)
    org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator.getGroupMembershipRoles(DefaultLdapAuthoritiesPopulator.java:241)
    org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator.getGrantedAuthorities(DefaultLdapAuthoritiesPopulator.java:210)
    org.springframework.security.ldap.authentication.LdapAuthenticationProvider.loadUserAuthorities(LdapAuthenticationProvider.java:213)
    org.springframework.security.ldap.authentication.AbstractLdapAuthenticationProvider.authenticate(AbstractLdapAuthenticationProvider.java:89)
    org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:174)
    org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:199)
    org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter.attemptAuthentication(UsernamePasswordAuthenticationFilter.java:94)
    org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:212)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    org.springframework.security.web.csrf.CsrfFilter.doFilterInternal(CsrfFilter.java:124)
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:64)
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56)
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:214)
    org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:177)
    org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
    org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262)


root cause 

javax.naming.PartialResultException: Unprocessed Continuation Reference(s); remaining name ''
    com.sun.jndi.ldap.LdapCtx.processReturnCode(LdapCtx.java:2917)
    com.sun.jndi.ldap.LdapCtx.processReturnCode(LdapCtx.java:2891)
    com.sun.jndi.ldap.LdapCtx.searchAux(LdapCtx.java:1846)
    com.sun.jndi.ldap.LdapCtx.c_search(LdapCtx.java:1769)
    com.sun.jndi.toolkit.ctx.ComponentDirContext.p_search(ComponentDirContext.java:392)
    com.sun.jndi.toolkit.ctx.PartialCompositeDirContext.search(PartialCompositeDirContext.java:358)
    com.sun.jndi.toolkit.ctx.PartialCompositeDirContext.search(PartialCompositeDirContext.java:341)
    javax.naming.directory.InitialDirContext.search(InitialDirContext.java:267)
    org.springframework.ldap.core.LdapTemplate.executeSearch(LdapTemplate.java:322)
    org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:363)
    org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:328)
    org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:629)
    org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:570)
    org.springframework.security.ldap.SpringSecurityLdapTemplate.searchForMultipleAttributeValues(SpringSecurityLdapTemplate.java:241)
    org.springframework.security.ldap.SpringSecurityLdapTemplate.searchForSingleAttributeValues(SpringSecurityLdapTemplate.java:166)
    org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator.getGroupMembershipRoles(DefaultLdapAuthoritiesPopulator.java:241)
    org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator.getGrantedAuthorities(DefaultLdapAuthoritiesPopulator.java:210)
    org.springframework.security.ldap.authentication.LdapAuthenticationProvider.loadUserAuthorities(LdapAuthenticationProvider.java:213)
    org.springframework.security.ldap.authentication.AbstractLdapAuthenticationProvider.authenticate(AbstractLdapAuthenticationProvider.java:89)
    org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:174)
    org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:199)
    org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter.attemptAuthentication(UsernamePasswordAuthenticationFilter.java:94)
    org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:212)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    org.springframework.security.web.csrf.CsrfFilter.doFilterInternal(CsrfFilter.java:124)
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:64)
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56)
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:214)
    org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:177)
    org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
    org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262)

有人可以向我解释为什么会这样吗?我该如何解决?不是 LDAP 方面的专家。如果您需要更多信息,请告诉我,我会更新问题。

我想我解决了我的问题。显然 LdapAuthenticationProviderConfigurer 中使用的 LdapAuthoritiesPopulator 不会忽略部分结果。所以我所做的是定义一个忽略部分结果的 DefaultAuthoritiesPopulator 并将其传递给我的 LdapAuthenticationProviderConfigurer.

以下是应用的更改:

@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
    auth.ldapAuthentication()
            .ldapAuthoritiesPopulator(authoritiesPopulator())
            .userSearchBase(userSearchBase)
            .userSearchFilter(userSearchFilter)
            .contextSource(contextSource());
}

public LdapAuthoritiesPopulator authoritiesPopulator() {
    DefaultLdapAuthoritiesPopulator populator =
            new DefaultLdapAuthoritiesPopulator(
                    contextSource(), userSearchBase);
    populator.setGroupSearchFilter(userSearchFilter);
    populator.setIgnorePartialResultException(true);

    return populator;
}