Spring 使用 ActiveDirectoryLdapAuthenticationProvider 和嵌入式 ldif 进行身份验证
Spring authentication using ActiveDirectoryLdapAuthenticationProvider and embedded ldif
我的一个客户要求是根据他的企业 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 隐藏在防火墙后面。它在部署后工作,但由于 cleints 安全策略,我无法在本地开发期间访问 AC。所以,我有一个想法,也许对于开发配置文件,我将使用嵌入式 LDAP 服务器(Java 的 UnboundID LDAP SDK)。我不是 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 文件中 "mock" ActiveDirectory(LDAP),以便 ActiveDirectoryLdapAuthenticationProvider 可以在身份验证期间使用它?
我遇到了同样的问题并找到了有效的解决方案,但我对此不是很满意。
以下是它对我的作用:
调整.ldif
文件
将 userPrincipalName
属性添加到您的 .ldif
文件并使用与 dn
相同的值填充它,在您的情况下:
dn: uid=john,ou=people,dc=test,dc=local
userPrincipalName: uid=john,ou=people,dc=test,dc=local
使用dn
而不是电子邮件地址进行身份验证
您在测试中使用 john@test.local
进行身份验证。要使其工作,您必须使用 dn
:uid=john,ou=people,dc=test,dc=local
进行这些更改后,针对嵌入式 LDAP 的身份验证在测试中起作用。
欢迎更好的解决方案!
我可以通过以下方式做到这一点。
- 定义文件并更改文件
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 ) )
- 包含用户
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
- 配置Spring引导属性:
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
将添加到 attributetypes
和 person
对象将在
objectClasses
在默认架构中。
要登录,您需要使用:
username: uid=john,ou=people,dc=test,dc=local
password: SomePassword
如果您将 ActiveDirectoryLdapAuthenticationProvider
与嵌入式 ldap 服务器一起使用,这是必需的解决方法。
我的一个客户要求是根据他的企业 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 隐藏在防火墙后面。它在部署后工作,但由于 cleints 安全策略,我无法在本地开发期间访问 AC。所以,我有一个想法,也许对于开发配置文件,我将使用嵌入式 LDAP 服务器(Java 的 UnboundID LDAP SDK)。我不是 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 文件中 "mock" ActiveDirectory(LDAP),以便 ActiveDirectoryLdapAuthenticationProvider 可以在身份验证期间使用它?
我遇到了同样的问题并找到了有效的解决方案,但我对此不是很满意。 以下是它对我的作用:
调整
.ldif
文件将
userPrincipalName
属性添加到您的.ldif
文件并使用与dn
相同的值填充它,在您的情况下:dn: uid=john,ou=people,dc=test,dc=local userPrincipalName: uid=john,ou=people,dc=test,dc=local
使用
dn
而不是电子邮件地址进行身份验证您在测试中使用
john@test.local
进行身份验证。要使其工作,您必须使用dn
:uid=john,ou=people,dc=test,dc=local
进行这些更改后,针对嵌入式 LDAP 的身份验证在测试中起作用。 欢迎更好的解决方案!
我可以通过以下方式做到这一点。
- 定义文件并更改文件
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 ) )
- 包含用户
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
- 配置Spring引导属性:
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
将添加到 attributetypes
和 person
对象将在
objectClasses
在默认架构中。
要登录,您需要使用:
username: uid=john,ou=people,dc=test,dc=local
password: SomePassword
如果您将 ActiveDirectoryLdapAuthenticationProvider
与嵌入式 ldap 服务器一起使用,这是必需的解决方法。