This guide is intended to help users migrate from Spring Security 3.x to Spring Security 4.x when using Java based configuration.
If you are looking to migrate from Spring Security 3.x to Spring Security 4.x when using XML Based configuration, click here

1. Introduction

As exploits against applications evolve, so must Spring Security.
As a major release version, the Spring Security team took the opportunity to make some non-passive changes which focus on:

4. Deprecations

A number of deprecations were removed in Spring Security 4 to clean up clutter.
The following section describes how to migrate each deprecation.

If you are using the Java configuration, there are many instances where you will be shielded from deprecation.
If you (or a non-spring library you use) do NOT use an API directly, then you will NOT be impacted.
This means typically a quick search in your workspace should allow you to find all the deprecations.

4.1. Related Links

For thoroughness we have include the related links in the table below.

This means that an ServiceAuthenticationDetailsSource was being created with these constructors:

new ServiceAuthenticationDetailsSource();
new ServiceAuthenticationDetailsSource(artifactId);

it needs to be updated to pass in the ServiceProperties as shown below:

new ServiceAuthenticationDetailsSource(serviceProperties);
new ServiceAuthenticationDetailsSource(serviceProperties, artifactId);

4.4. spring-security-core

This section describes all of the deprecated APIs within the spring-security-core module.
If you are not using the spring-security-core module or have already completed this task, you can safely skip to spring-security-openid.

4.4.1. SecurityConfig

SecurityConfig.createSingleAttributeList(String) was removed in favor of using SecurityConfig.createList(String…​).
This means if you have something like this:

4.4.3. UserDetailsWrapper

UserDetailsWrapper was deprecated in favor of using RoleHierarchyAuthoritiesMapper.
Typically users would not use the UserDetailsWrapper directly. However, if they are they can use RoleHierarchyAuthoritiesMapper
For example, if the following code is present:

4.4.4. AbstractAccessDecisionManager

The default constructor for AbstractAccessDecisionManager has been deprecated along with the setDecisionVoters method.
Naturally, this impacts the subclasses AffirmativeBased, ConsensusBased, and UnanimousBased.
For example, this means that if you are using the following:

This impacts the subclasses AccountStatusException, AccountExpiredException, BadCredentialsException, CredentialsExpiredException, DisabledException, LockedException, and UsernameNotFoundException.
If use are using any of these constructors, simply remove the additional argument.
For example, the following is changed from:

new LockedException("Message", userDetails);

to:

new LockedException("Message");

4.4.6. AnonymousAuthenticationProvider

AnonymousAuthenticationProvider default constructor and setKey method was deprecated in favor of using constructor injection.
For example, if you have the following:

4.4.8. ProviderManager

ProviderManager has removed the deprecated default constructor and the correspdonding setter methods in favor of using constructor injection.
It has also removed the clearExtraInformation property since the AuthenticationException had the extra information property removed.

4.4.12. spring-security-openid

This section describes all of the deprecated APIs within the spring-security-openid module.
If you are not using the spring-security-openid module or have already completed this task, you can safely skip to spring-security-taglibs.

4.4.13. OpenID4JavaConsumer

The OpenID4JavaConsumer constructors that accept List<OpenIDAttribute> have been removed in favor of using an AxFetchListFactory.
For example:

4.5. spring-security-taglibs

This section describes all of the deprecated APIs within the spring-security-taglibs module.
If you are not using the spring-security-taglibs module or have already completed this task, you can safely skip to spring-security-web.

4.6. spring-security-web

This section describes all of the deprecated APIs within the spring-security-web module.
If you are not using the spring-security-web module or have already completed this task, you can safely skip to [m3to4-xmlnamespace-defaults].

4.6.1. FilterChainProxy

FilterChainProxy removed the setFilterChainMap method in favor of constructor injection.
For example, if you have the following:

4.6.7. AbstractRememberMeServices

AbstractRememberMeServices and its subclasses PersistentTokenBasedRememberMeServices and TokenBasedRememberMeServices removed the default constructor and the setKey and setUserDetailsService methods in favor of constructor injection.

4.6.8. PersistentTokenBasedRememberMeServices

AbstractRememberMeServices and its subclasses PersistentTokenBasedRememberMeServices and TokenBasedRememberMeServices removed the default constructor and the setKey and setUserDetailsService methods in favor of constructor injection.
For example:

4.6.10. TokenBasedRememberMeServices

AbstractRememberMeServices and its subclasses PersistentTokenBasedRememberMeServices and TokenBasedRememberMeServices removed the default constructor and the setKey and setUserDetailsService methods in favor of constructor injection.
For example:

4.6.11. ConcurrentSessionControlStrategy

ConcurrentSessionControlStrategy was replaced with ConcurrentSessionControlAuthenticationStrategy.
Previously ConcurrentSessionControlStrategy could not be decoupled from SessionFixationProtectionStrategy.
Now it is completely decoupled.
For example, the following:

6.1. Related Links

6.2. CasAuthenticationFilter

The CasAuthenticationFilter filterProcessesUrl property default value changed from "/j_spring_cas_security_check" to "/login/cas".
This means if the filterProcessesUrl property is not explicitly specified, then the configuration will need updated.
For example, if an application using Spring Security 3.2.x contains a configuration similar to the following:

6.3. SwitchUserFilter

The SwitchUserFilter switchUserUrl property default value changed from "/j_spring_security_switch_user" to "/login/impersonate".
This means if the switchUserUrl property is not explicitly specified, then the configuration will need updated.

The SwitchUserFilter exitUserUrl property default value changed from "/j_spring_security_exit_user" to "/logout/impersonate".
This means if the exitUserUrl property is not explicitly specified, then the configuration will need updated.

For example, if an application using Spring Security 3.2.x contains a configuration similar to the following:

6.4. LogoutFilter

The LogoutFilter filterProcessesUrl property default value changed from "/j_spring_security_logout" to "/logout".
This means if the filterProcessesUrl property is not explicitly specified, then the configuration will need updated.

For example, if an application using Spring Security 3.2.x contains a configuration similar to the following:

Alternatively, the URL’s within the application can be updated from "/j_spring_security_logout" to "/logout".

7. Header Configuration Changes

In Spring Security 3.x the HTTP Response Header configuration was difficult to customize.
If an application overrode a single default, then all of the other defaults would be disabled.
This was unintuitive, error prone, and most importantly not very secure.

Spring Security 4.x has changed both the Java Configuration and XML Configuration to require explicit disabling of defaults.
Additionally, it has made customizing a single default much easier.

If an application has customized the HTTP Response Header Configuration in any way, they are impacted by this change.
If the application used the defaults, then they are not impacted by this change.

A detailed description of how to configure Security HTTP Response Headers can be found in the reference.
Below we highlight the changes in configuring the Security HTTP Response Headers between 3.x and 4.x.

7.2.2. Migrate Headers Java Config Method Chaining

In Spring Security 3.x, the following configuration

http
// ...
.headers()
.cacheControl()
.frameOptions();

would compile succesfully.
However, Spring Security 4.x it will not compile.
This is due to the fact that additional options needed to be added to support customizing the configuration.
Instead, we must chain the headers customizations with .and().
For example: