Spring 引导原因中使用 LDAP 进行身份验证时出错:[LDAP:错误代码 50 - 访问权限不足]

Error authenticating with LDAP in Spring Boot Reason: [LDAP: error code 50 - Insufficient Access Rights]

我正在尝试制作一个带有 spring 引导的验证页面,以验证 LDAP 服务器中存在的用户。我的代码是这样的:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.encoding.LdapShaPasswordEncoder;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.ldap.DefaultSpringSecurityContextSource;

import java.util.Arrays;

@Configuration
@EnableGlobalMethodSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
        .authorizeRequests()
        .anyRequest().fullyAuthenticated()
        .and()
        .formLogin();
}

@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth
        .ldapAuthentication()
        .userSearchBase("ou=people")
        .userSearchFilter("(cn={0})")
        .contextSource(contextSource())
        .passwordCompare()
        .passwordAttribute("userPassword");
}

@Bean
public DefaultSpringSecurityContextSource contextSource(){
    return new DefaultSpringSecurityContextSource(Arrays.asList("ldap://localhost:389"),"dc=myCompany,dc=org");
}

}

问题是我收到以下错误,但我似乎不明白它是从哪里来的。

Reason: [LDAP: error code 50 - Insufficient Access Rights]; nested exception is javax.naming.NoPermissionException: [LDAP: error code 50 - Insufficient Access Rights]; remaining name 'cn=nameEntered,ou=people'

任何帮助都会有所帮助。

问题很可能与您尝试将 userPassword 作为 LDAP 搜索查询的一部分提取有关。大多数服务器按照 this RFC.

中的描述保护此属性

所以这个问题可能有两种不同的解决方案:

  • 与您的 LDAP 服务器管理员联系并创建一个能够读取该属性的进程帐户(manual for OpenLDAP here). This assumes your userPassword attribute is a cleartext password, if it's not you'll need to use a password encoder as described here

  • 切换到绑定认证。这不是使用特权帐户从用户那里检索密码,而是作为您尝试验证的用户绑定到 LDAP,不需要任何特殊权限。但是,它只会让您访问用户有权访问的属性。这是described here。您可以这样配置它:

<ldap-authentication-provider user-dn-pattern="uid={0},ou=people"/>

在任何一种情况下,您都应该切换到 ldaps:// 而不是 ldap://,因为密码(或哈希值)将以明文形式通过网络传输。

我不熟悉 Spring API。

但我读了 API 调用,因为它做了两件事:

  1. 发送搜索操作以获取用户的 LDAP 条目的可分辨名称 (DN)。
  2. 为此 DN 发送比较操作,断言类型为 userPassord,输入密码作为断言值。

其中一个操作失败。异常traceback大概可以看出是哪一个

在任何情况下,通过与 OpenLDAP 的比较操作来验证密码是没有意义的,因为它仅在存储明文密码时有效。这是熟练的 LDAP 管理员可能不会做的事情。

所以尝试找到API方法来使用绑定操作来检查找到的用户DN的密码。请注意,这可能需要在您的客户端应用程序中使用系统帐户身份验证才能获取搜索结果。

在某些情况下,您可以直接从用户名派生出用户 DN。在这种情况下,您可以只发送绑定操作而无需事先进行系统绑定。但这需要固定的目录信息树 (DIT) 布局。