mirror of
https://github.com/spring-projects/spring-security.git
synced 2025-06-22 12:02:14 +00:00
Add ApacheDS Migration Steps
Issue gh-13852
This commit is contained in:
parent
fc6650111a
commit
09983e2349
@ -9,3 +9,248 @@ Consequently, support for ApacheDS will be discontinued in version 7.0.
|
||||
|
||||
If you are currently using ApacheDS as an embedded LDAP server, we recommend migrating to https://ldap.com/unboundid-ldap-sdk-for-java/[UnboundId].
|
||||
You can find instructions in xref:servlet/authentication/passwords/ldap.adoc#servlet-authentication-ldap-embedded[this section] that describe how to set up an embedded UnboundId LDAP server.
|
||||
|
||||
To migrate, you will need to consider the following:
|
||||
|
||||
1. <<ldap-migrate-apacheds-unboundid-dependencies,Dependencies>>
|
||||
2. <<ldap-migrate-apacheds-unboundid-container,Container Declaration>>
|
||||
3. <<ldap-migrate-apacheds-unboundid-password-encoding,Password Encoding>>
|
||||
4. <<ldap-migrate-apacheds-unboundid-password-encoding,Password Hiding>>
|
||||
|
||||
[[ldap-migrate-apacheds-unboundid-dependencies]]
|
||||
=== Switch Your Dependencies
|
||||
|
||||
To use UnboundID, you will at least need to remove the ApacheDS dependencies:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Maven::
|
||||
+
|
||||
[source,maven,role="primary"]
|
||||
----
|
||||
<dependency>
|
||||
<groupId>org.apache.directory.server</groupId>
|
||||
<artifactId>apacheds-core</artifactId>
|
||||
<version>1.5.5</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.directory.server</groupId>
|
||||
<artifactId>apacheds-server-jndi</artifactId>
|
||||
<version>1.5.5</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
----
|
||||
|
||||
Gradle::
|
||||
+
|
||||
[source,gradkle,role="secondary"]
|
||||
----
|
||||
implementation("org.apache.directory.server:apacheds-server-jndi")
|
||||
implementation("org.apache.directory.server:apacheds-core")
|
||||
----
|
||||
======
|
||||
|
||||
and replace them with UnboundID:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Maven::
|
||||
+
|
||||
[source,maven,role="primary"]
|
||||
----
|
||||
<dependency>
|
||||
<groupId>com.unboundid</groupId>
|
||||
<artifactId>unboundid-ldapsdk</artifactId>
|
||||
<version>7.0.3</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
----
|
||||
|
||||
Gradle::
|
||||
+
|
||||
[source,gradkle,role="secondary"]
|
||||
----
|
||||
implementation("org.apache.directory.server:apacheds-server-jndi")
|
||||
implementation("org.apache.directory.server:apacheds-core")
|
||||
----
|
||||
======
|
||||
|
||||
If you are accepting the LDAP server defaults, this is likely all you will need to do.
|
||||
|
||||
[[ldap-migrate-apacheds-unboundid-container]]
|
||||
=== Change Server Declaration
|
||||
|
||||
If you are declaring an ApacheDS server, then you will need to change its declaration.
|
||||
Your configuration may vary somewhat from the following.
|
||||
Change this:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,role="primary"]
|
||||
----
|
||||
@Bean
|
||||
EmbeddedLdapServerContainer ldapContainer() {
|
||||
EmbeddedLdapServerContainer container =
|
||||
new ApacheDSContainer("dc=springframework,dc=org", "classpath:test-server.ldif");
|
||||
container.setPort(0);
|
||||
return container;
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,role="secondary"]
|
||||
----
|
||||
@Bean
|
||||
fun ldapContainer(): EmbeddedLdapServerContainer {
|
||||
val container =
|
||||
ApacheDSContainer("dc=springframework,dc=org", "classpath:test-server.ldif")
|
||||
container.setPort(0)
|
||||
return container
|
||||
}
|
||||
----
|
||||
|
||||
Xml::
|
||||
+
|
||||
[source,xml,role="secondary"]
|
||||
----
|
||||
<ldap-server mode="apacheds"/>
|
||||
----
|
||||
======
|
||||
|
||||
to this:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,role="primary"]
|
||||
----
|
||||
@Bean
|
||||
EmbeddedLdapServerContainer ldapContainer() {
|
||||
EmbeddedLdapServerContainer container =
|
||||
new UnboundIdContainer("dc=springframework,dc=org", "classpath:test-server.ldif");
|
||||
container.setPort(0);
|
||||
return container;
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,role="secondary"]
|
||||
----
|
||||
@Bean
|
||||
fun ldapContainer(): EmbeddedLdapServerContainer {
|
||||
val container =
|
||||
UnboundIdContainer("dc=springframework,dc=org", "classpath:test-server.ldif")
|
||||
container.setPort(0)
|
||||
return container
|
||||
}
|
||||
----
|
||||
|
||||
Xml::
|
||||
+
|
||||
[source,xml,role="secondary"]
|
||||
----
|
||||
<ldap-server mode="unboundid"/>
|
||||
----
|
||||
======
|
||||
|
||||
|
||||
[[ldap-migrate-apacheds-unboundid-password-encoding]]
|
||||
=== Configure Password Encoding
|
||||
|
||||
Apache Directory Server supports binding with SHA-hashed passwords, but UnboundID does not.
|
||||
|
||||
If you run into trouble with binding users with SHA-hashed passwords, move to Spring Security's `PasswordComparisonAuthenticator` by providing a password encoder to the authentication provider:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,role="primary"]
|
||||
----
|
||||
@Bean
|
||||
AuthenticationManager ldapAuthenticationManager(BaseLdapPathContextSource contextSource) {
|
||||
LdapPasswordComparisonAuthenticationManagerFactory factory =
|
||||
new LdapPasswordComparisonAuthenticationManagerFactory(
|
||||
contextSource, new LdapShaPasswordEncoder());
|
||||
// ...
|
||||
return factory.createAuthenticationManager();
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,role="secondary"]
|
||||
----
|
||||
@Bean
|
||||
fun ldapAuthenticationManager(val contextSource: BaseLdapPathContextSource): AuthenticationManager {
|
||||
val factory = LdapPasswordComparisonAuthenticationManagerFactory(
|
||||
contextSource, LdapShaPasswordEncoder())
|
||||
// ...
|
||||
return factory.createAuthenticationManager()
|
||||
}
|
||||
----
|
||||
|
||||
Xml::
|
||||
+
|
||||
[source,xml,role="secondary"]
|
||||
----
|
||||
<auhentication-manager>
|
||||
<ldap-authentication-provider>
|
||||
<password-compare>
|
||||
<password-encoder ref='pe' />
|
||||
</password-compare>
|
||||
</ldap-authentication-provider>
|
||||
</auhentication-manager>
|
||||
<b:bean id='pe' class='org.springframework.security.crypto.password.LdapShaPasswordEncoder' />
|
||||
----
|
||||
======
|
||||
|
||||
[WARN]
|
||||
====
|
||||
Hashing passwords with `+{SHA}+` is not recommended.
|
||||
Please migrate to BCrypt, SCrypt, or Argon2 as soon as possible.
|
||||
You can use the same approach above to provide the corresponding password encoder.
|
||||
====
|
||||
|
||||
[[ldap-migrate-apacheds-unboundid-password-hiding]]
|
||||
=== Configure Password Hiding
|
||||
|
||||
ApacheDS is configured by Spring Security to hide the `userPassword` attribute from search results unless explicitly queried.
|
||||
UnboundID does not support this.
|
||||
|
||||
You can achieve this behavior with a custom `InMemoryOperationInterceptor` like the following:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
static class PasswordRemovingOperationInterceptor
|
||||
extends InMemoryOperationInterceptor {
|
||||
|
||||
@Override
|
||||
public void processSearchEntry(InMemoryInterceptedSearchEntry entry) {
|
||||
if (!entry.getRequest().getAttributeList().contains("userPassword")) {
|
||||
if (entry.getSearchEntry().getAttribute("userPassword") != null) {
|
||||
Entry old = entry.getSearchEntry();
|
||||
Collection<Attribute> attributes = old.getAttributes().stream()
|
||||
.filter(attribute ->
|
||||
!"userPassword".equals(attribute.getName()))
|
||||
.collect(Collectors.toList());
|
||||
Entry withoutPassword = new Entry(old.getDN(), attributes);
|
||||
entry.setSearchEntry(withoutPassword);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
It is better to secure passwords by hashing them and by using queries that identify the specific columns that you need.
|
||||
====
|
||||
|
||||
`UnboundIdContainer` does not currently have a way to register a custom `InMemoryOperationInterceptor`, but you can either copy the contents of `UnboundIdContainer` or use Spring LDAP Test's `EmbeddedLdapServer` builder in order to provide this interceptor and confirm your application's readiness.
|
||||
|
@ -363,7 +363,7 @@ This section addresses common Spring Security architecture questions:
|
||||
. <<appendix-faq-namespace-to-bean-mapping>>
|
||||
. <<appendix-faq-role-prefix>>
|
||||
. <<appendix-faq-what-dependencies>>
|
||||
. <<appendix-faq-apacheds-deps>>
|
||||
. <<appendix-faq-unboundid-deps>>
|
||||
. <<appendix-faq-what-is-userdetailservice>>
|
||||
|
||||
|
||||
@ -412,9 +412,42 @@ The reference manual also includes <<appendix-namespace,an appendix>> that lists
|
||||
If you build your project with Maven, adding the appropriate Spring Security modules as dependencies to your `pom.xml` file automatically pulls in the core jars that the framework requires.
|
||||
Any that are marked as "`optional`" in the Spring Security `pom.xml` files have to be added to your own `pom.xml` file if you need them.
|
||||
|
||||
[[appendix-faq-unboundid-deps]]
|
||||
=== What dependences are needed to run an embedded UnboundID LDAP server?
|
||||
|
||||
You need to add the following dependency to your project:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Maven::
|
||||
+
|
||||
[source,maven,role="primary"]
|
||||
----
|
||||
<dependency>
|
||||
<groupId>com.unboundid</groupId>
|
||||
<artifactId>unboundid-ldapsdk</artifactId>
|
||||
<version>7.0.1</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
----
|
||||
|
||||
Gradle::
|
||||
+
|
||||
[source,gradle,role="secondary"]
|
||||
----
|
||||
implementation 'com.unboundid:unboundid-ldapsdk:7.0.1'
|
||||
----
|
||||
======
|
||||
|
||||
[[appendix-faq-apacheds-deps]]
|
||||
=== What dependencies are needed to run an embedded ApacheDS LDAP server?
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
Spring Security 7 removes support for Apache DS.
|
||||
Please use <<appendix-faq-unboundid-deps,UnboundID>> instead.
|
||||
====
|
||||
|
||||
If you use Maven, you need to add the following to your `pom.xml` file dependencies:
|
||||
|
||||
[source]
|
||||
|
@ -225,9 +225,8 @@ fun ldapContainer(): UnboundIdContainer {
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
Spring Security uses ApacheDS 1.x, which is no longer maintained.
|
||||
Unfortunately, ApacheDS 2.x has only released milestone versions with no stable release.
|
||||
Once a stable release of ApacheDS 2.x is available, we will consider updating.
|
||||
Spring Security 7 removes support for Apache DS.
|
||||
Please use <<servlet-authentication-ldap-unboundid,UnboundID>> instead.
|
||||
====
|
||||
|
||||
If you wish to use https://directory.apache.org/apacheds/[Apache DS], specify the following dependencies:
|
||||
|
Loading…
x
Reference in New Issue
Block a user