如何正确使用配置器类实现 Spring Security Ldap 身份验证?

Posted

技术标签:

【中文标题】如何正确使用配置器类实现 Spring Security Ldap 身份验证?【英文标题】:How to implement Spring Security Ldap authentication using the configurer class correctly? 【发布时间】:2015-08-12 11:28:23 【问题描述】:

您好,我正在尝试使用 WebSecurityConfigurerAdapter 类实现 Spring 的 ldap 身份验证。

到目前为止,我可以通过 in memory 方法甚至我公司的 ldap 服务器进行身份验证,但是后一种方法我只能在我创建新上下文时传递硬编码的 userDN 和密码时才能进行身份验证,如果我不这样做' t 创建一个新的上下文或者我没有输入 userDN 和密码,jvm 会抛出我:

Caused by: javax.naming.NamingException: [LDAP: error code 1 - 000004DC: LdapErr: DSID-0C0906E8, comment: In order to perform this operation a successful bind must be completed on the connection., data 0, v1db1\u0000]; Remaining name: '/'

我的问题是,如何从登录表单中获取用户密码和 userDN,以便将其放入上下文中?如果这不可能,我怎样才能获得密码和 userDn 的上下文?

这是我的代码:

@Configuration
@EnableWebMvcSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter 

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception 

        auth.ldapAuthentication().userSearchFilter("(&(objectClass=user)(sAMAccountName=0))")
          .groupSearchFilter("(&(memberOf:1.2.840.113556.1.4.1941:=CN=DL - DC859 - MIDDLEWARE,OU=Dyn,OU=Dist,OU=Security Groups,OU=POP,DC=pop,DC=corp,DC=local))")
          .contextSource(getLdapContextSource());
    

    private LdapContextSource getLdapContextSource() throws Exception 
        LdapContextSource cs = new LdapContextSource();
        cs.setUrl("ldap://tcp-prd.pop.corp.local:389");
        cs.setBase("DC=pop,DC=corp,DC=local");
        cs.setUserDn("t8951435@pop.corp.local");
        cs.setPassword("mypassword");
        cs.afterPropertiesSet();
        return cs;
    

    @Override
    protected void configure(HttpSecurity http) throws Exception 
        http.authorizeRequests()
            .antMatchers("/resources/**").permitAll()
            .anyRequest().authenticated()
            .and()
            .formLogin()
            .loginPage("/login")
            .permitAll();     
    


谢谢。

【问题讨论】:

使用LDAP认证有两种模式。首先,您知道如何根据用户名构建用户的 DN(它甚至可以是 DN 本身)。其次,您需要执行 LDAP 搜索来查找用户的 DN。对于后者,您需要进行技术登录,以便 LDAP 身份验证组件可以找到用户条目。这就是你应该用来判断你的例子。您应该要求您的 LDAP 管理员为您的应用程序创建技术帐户并在您的 LdapContextSource 中使用它。 我知道 userDN 将永远是用户在用户名框中输入的内容 + @pop.corp.local。我首先认为 auth 知道上下文并在其中包含用户名,但这似乎不是真的,因此我必须创建一个新的上下文。我只是不知道如何从那里获取凭据。 那不是DN,是域登录名。但也许您可以使用它登录到 Active Directory。我不确定。 有两个字段,DN和userDN。 DN 是“DC=pop,DC=corp,DC=local”。 不。 DN 是由RFC 4514 定义的特定事物。基础 DN 是上下文基础 DN,即 LDAP 树的基础(即您的树开始的位置)。您所指的 userDN 也应该是 DN。您没有提供 DN,而是提供用户的 principal name。 【参考方案1】:

我终于从this 帖子中弄明白了。我仍然不知道如何设置组过滤器,但至少现在我可以绑定到服务器了。

 @Bean
 public ActiveDirectoryLdapAuthenticationProvider activeDirectoryLdapAuthenticationProvider() 
     ActiveDirectoryLdapAuthenticationProvider provider = new ActiveDirectoryLdapAuthenticationProvider("pop.corp.local", 
             "ldap://tcp-prd.pop.corp.local:389");
        provider.setConvertSubErrorCodesToExceptions(true);
        provider.setUseAuthenticationRequestCredentials(true);
        return provider;
 

@Bean
public LoggerListener loggerListener() 
    return new LoggerListener();



@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception 
    auth.authenticationProvider(activeDirectoryLdapAuthenticationProvider());


    @Override
protected void configure(HttpSecurity http) throws Exception 
    http
        .authorizeRequests()
            .antMatchers("/resources/**").permitAll()
            .anyRequest().authenticated()
            .and()
        .formLogin()
            .loginPage("/login")
            .permitAll();     

编辑:我终于找到了如何按组过滤。事实证明,他们在 ActiveDirectoryLdapAuthenticationProvider 类 v3.2.6 中添加了一个 setSearchFilter() 方法。因为我使用的是旧版本,所以我从来不知道这一点。所以我用该方法制作了一个类的副本,并创建了一个 buildFilter 方法来创建传递给 setSearchFilter 的过滤器字符串。

【讨论】:

以上是关于如何正确使用配置器类实现 Spring Security Ldap 身份验证?的主要内容,如果未能解决你的问题,请参考以下文章

Spring加载加密的配置文件

Spring中的Jdbc事务管理

如何正确实现使用 Spring MVC\Boot 返回图像列表的 REST 服务?

Spring 应用程序在 8 小时后失去与 MySql 的连接。如何正确配置?

Spring MVC 无法正确配置 Dispatcher Servlet

带有 spring-boot 和 spring-security 的 JWT