【问题标题】:Spring authentication using ActiveDirectoryLdapAuthenticationProvider and embedded ldif使用 ActiveDirectoryLdapAuthenticationProvider 和嵌入式 ldif 的 Spring 身份验证
【发布时间】:2020-02-18 09:07:39
【问题描述】:

我的客户要求之一是根据他的公司 ActiveDirectory (LDAP) 对用户进行身份验证。所以我使用了标准的 ActiveDirectoryLdapAuthenticationProvider,它就像一个魅力。

@Bean
public ActiveDirectoryLdapAuthenticationProvider activeDirectoryLdapAuthenticationProvider() {
    ActiveDirectoryLdapAuthenticationProvider adProvider = new ActiveDirectoryLdapAuthenticationProvider(
            ldapConfig.getLdapDomain(), ldapConfig.getLdapUrl(), ldapConfig.getLdapRoot());
    adProvider.setConvertSubErrorCodesToExceptions(true);
    adProvider.setUseAuthenticationRequestCredentials(true);
    adProvider.setSearchFilter(ldapConfig.getLdapSearchFilter());
    return adProvider;
}

问题是客户端 AC 隐藏在防火墙后面。它在部署后工作,但由于客户端安全策略,我在本地开发期间无法访问 AC。所以,我有一个想法,也许对于开发配置文件,我将使用嵌入式 LDAP 服务器(UnboundID LDAP SDK for Java)。我不是 LDAP 专家,但我以某种方式编写了简单的 ldif 文件,它看起来像这样:

dn: dc=test,dc=local
objectclass: top
objectclass: domain
objectclass: extensibleObject
dc: test
# Organizational Units
dn: ou=groups,dc=test,dc=local
objectclass: top
objectclass: organizationalUnit
ou: groups
dn: ou=people,dc=test,dc=local
objectclass: top
objectclass: organizationalUnit
ou: people
# Users
dn: uid=john,ou=people,dc=test,dc=local
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
cn: John Doe
sn: John
uid: john
password: johnspassword
# Create Groups
dn: cn=administrators,ou=groups,dc=test,dc=local
objectclass: top
objectclass: groupOfUniqueNames
cn: administrators
ou: administrator
uniqueMember: uid=john,ou=people,dc=test,dc=local

我还配置了嵌入式 ldap 属性:

spring.ldap.embedded.base-dn=dc=test,dc=local
spring.ldap.embedded.ldif=classpath:localldapactivedirectory.ldif
spring.ldap.embedded.port=12345
spring.ldap.embedded.url=ldap://localhost:12345/
spring.ldap.embedded.validation.enabled=false

UnboundID 对此没有任何问题,但正如您猜测的那样,我在身份验证期间遇到了问题:

[LDAP: error code 34 - Unable to parse bind DN 'john@test.local':  Unable to parse string 'john@test.local' as a DN because it does not have an equal sign after RDN attribute 'john@test.local'.]; nested exception is javax.naming.InvalidNameException: [LDAP: error code 34 - Unable to parse bind DN 'john@test.local':  Unable to parse string 'user_cms@test.com' as a DN because it does not have an equal sign after RDN attribute 'john@test.local'.]

为了向您展示全貌,我添加了在身份验证尝试期间发生的错误(在自定义身份验证服务中):

Authentication authentication = authenticationManagerBuilder.getObject()
            .authenticate(authenticationToken);

我推测是因为我的 ldif 文件太简单了。它适用于 vanilla Ldap 身份验证提供程序,但不适用于 ActiveDirectoryLdapAuthenticationProvider。

是否有人知道如何在 ldif 文件中“模拟”ActiveDirectory(LDAP),以便 ActiveDirectoryLdapAuthenticationProvider 可以在身份验证期间使用它?

【问题讨论】:

  • 很久了,你找到解决办法了吗?

标签: java spring authentication active-directory ldap


【解决方案1】:

我遇到了同样的问题并找到了一个可行的解决方案,但我对此并不满意。 这对我来说是这样的:

  1. 调整.ldif文件

    userPrincipalName 属性添加到您的.ldif 文件中,并用与dn 相同的值填充它:

    dn: uid=john,ou=people,dc=test,dc=local
    userPrincipalName: uid=john,ou=people,dc=test,dc=local
    
  2. 使用dn 代替电子邮件地址进行身份验证

    您在测试中使用john@test.local 进行身份验证。为了使它工作,你必须使用dn:uid=john,ou=people,dc=test,dc=local

在这些更改之后,针对嵌入式 LDAP 的身份验证在测试中起作用。 欢迎提供更好的解决方案!

【讨论】:

  • 不幸的是它没有帮助,有下一个错误:引起:javax.naming.AuthenticationException:[LDAP:错误代码 49 - 无法绑定为用户 'uid=super,ou=people,dc =test,dc=com@test.com' 因为服务器中不存在这样的条目。]
【解决方案2】:

我可以通过以下方式做到这一点。

  1. 定义文件并更改文件ldap-schema.ldif 中的架构。注意,模式需要像最初定义的那样定义,而不是像这里LDIF Format for Adding Schema Elements这样的更改格式:
dn: cn=schema
objectClass: top
objectClass: ldapSubEntry
objectClass: subschema
cn: schema
attributetypes: ( 1.2.3.4.5.6.7 NAME 'userPrincipalName' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE )
objectClasses: ( 7.8.9.9
                 NAME 'user'
                 SUP organizationalPerson
                 MUST (cn $
                        userPrincipalName ) )
  1. 带有用户test-server.ldif的Ldif文件:
dn: dc=test,dc=local
objectclass: top
objectclass: domain
objectclass: extensibleObject
dc: test

dn: uid=john,ou=people,dc=test,dc=local
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectClass: user
cn: John Doe
sn: John
uid: john
userPrincipalName: uid=john,ou=people,dc=test,dc=local
userPassword: SomePassword

  1. 配置 Spring Boot 属性:
spring.ldap.embedded.base-dn=dc=test,dc=local
spring.ldap.embedded.ldif=classpath:test-server.ldif
spring.ldap.embedded.validation.schema=classpath:ldap-schema.ldif
spring.ldap.embedded.port=12345
spring.ldap.embedded.url=ldap://localhost:12345/

EmbeddedLdapAutoConfiguration 将默认模式与ldap-schema.ldif 中定义的模式合并,结果userPrincipalName 将添加到attributetypesperson 对象将在 objectClasses 在默认架构中。

要登录,您需要使用:

username: uid=john,ou=people,dc=test,dc=local
password: SomePassword

如果您将 ActiveDirectoryLdapAuthenticationProvider 与嵌入式 ldap 服务器一起使用,这是必需的解决方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-04-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-17
    • 2018-03-28
    • 2012-06-19
    • 2016-08-12
    相关资源
    最近更新 更多