Spring Security: Global AuthenticationManager without the WebSecurityConfigurerAdapter - spring-boot

Im trying to get rid of WebSecurityConfigurerAdapter. The AuthenticationManager is configured like the following:
#Configuration
#EnableGlobalMethodSecurity(prePostEnabled = true)
public static class DefaultSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
#Bean
public AuthenticationManager authenticationManager() throws Exception {
return super.authenticationManager();
}
#Override
protected void configure(AuthenticationManagerBuilder auth)
throws Exception {
auth.userDetailsService(userDetailsService())
.passwordEncoder(passwordEncoder());
}
Now without the WebSecurityConfigurerAdapter i define the global AuthenticationManager like this:
#Configuration
#EnableGlobalMethodSecurity(prePostEnabled = true)
public static class DefaultSecurityConfig {
#Bean
public AuthenticationManager authenticationManager(AuthenticationManagerBuilder auth ) throws Exception {
return auth.userDetailsService(userDetailsService())
.passwordEncoder(passwordEncoder()).and().build();
}
And i get the error:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration': Unsatisfied dependency expressed through method 'setFilterChains' parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'defaultSecurityFilterChain' defined in class path resource [org/springframework/boot/autoconfigure/security/servlet/SpringBootWebSecurityConfiguration.class]: Unsatisfied dependency expressed through method 'defaultSecurityFilterChain' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.security.config.annotation.web.configuration.HttpSecurityConfiguration.httpSecurity' defined in class path resource [org/springframework/security/config/annotation/web/configuration/HttpSecurityConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.security.config.annotation.web.builders.HttpSecurity]: Factory method 'httpSecurity' threw exception; nested exception is java.lang.IllegalStateException: Cannot apply org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration$EnableGlobalAuthenticationAutowiredConfigurer#536a79bd to already built object
Im using Spring Boot v2.6.4
I'm stuck here for a while i would appreciate any help

Replace
#Bean
public AuthenticationManager authenticationManager(AuthenticationManagerBuilder auth ) throws Exception {
return auth.userDetailsService(userDetailsService())
.passwordEncoder(passwordEncoder()).and().build();
}
by
#Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration)
throws Exception {
return authenticationConfiguration.getAuthenticationManager();
}

In my project, I needed to use the AuthenticationManager in the Controller, to make a custom login. Then I declare:
#RestController
#RequestMapping("/api/login")
#Slf4j
#RequiredArgsConstructor
public class LoginResource {
private final AuthenticationManager authenticationManager;
....
}
In SecurityConfig:
#Configuration
#EnableWebSecurity
#RequiredArgsConstructor
#EnableGlobalMethodSecurity(securedEnabled = true)
public class SecurityConfig {
private final JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
private final JwtRequestFilter jwtRequestFilter;
private final UserDetailsService jwtUserDetailsService;
#Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers(HttpMethod.POST, "/api/login").permitAll()
.anyRequest().authenticated()
.and()
.exceptionHandling().authenticationEntryPoint(jwtAuthenticationEntryPoint).and().sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
// Add a filter to validate the tokens with every request
http.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
return http.build();
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Bean
public AuthenticationManager authenticationManagerBean(HttpSecurity http) throws Exception {
AuthenticationManagerBuilder authenticationManagerBuilder = http.getSharedObject(AuthenticationManagerBuilder.class);
authenticationManagerBuilder.userDetailsService(jwtUserDetailsService).passwordEncoder(passwordEncoder());
return authenticationManagerBuilder.build();
}
}
Then Works fine to me!!

Replace your code with this section below.
Hope it works, working fine in my code
#Bean
public AuthenticationManager authenticationManagerBean(HttpSecurity http) throws Exception {
AuthenticationManagerBuilder authenticationManagerBuilder = http.getSharedObject(AuthenticationManagerBuilder.class);
authenticationManagerBuilder
.userDetailsService(jwtUserDetailsService)
.passwordEncoder(passwordEncoder());
return authenticationManagerBuilder.build();
}

Related

Getting The bean 'authenticationManagerBuilder', defined in class path resource ... could not be registered

Im trying to implement authentication with Spring boot 3 like this :
#Configuration
#EnableWebSecurity
public class WebSecurityConfig {
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.authorizeHttpRequests((authz) -> authz
.requestMatchers("/webjars/**", "/resources/**", "/css/**", "/images/**").permitAll().anyRequest()
.authenticated()).formLogin((form) -> form.loginPage("/login").usernameParameter("email").permitAll())
.httpBasic(withDefaults());
return http.build();
}
#Bean
public UserDetailsService UserDetailsService() {
return new UserDetailsService();
}
public DaoAuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
authenticationProvider.setUserDetailsService(UserDetailsService());
authenticationProvider.setPasswordEncoder(passwordEncoder());
return authenticationProvider;
}
#Bean
public void authenticationManagerBuilder(AuthenticationManagerBuilder authConfiguration) throws Exception {
authConfiguration.authenticationProvider(authenticationProvider());
}
}
and getting this error :
*************************** APPLICATION FAILED TO START
Description:
The bean 'authenticationManagerBuilder', defined in class path
resource [com/test/admin/security/WebSecurityConfig.class], could not
be registered. A bean with that name has already been defined in class
path resource
[org/springframework/security/config/annotation/authentication/configuration/AuthenticationConfiguration.class]
and overriding is disabled.
Action:
Consider renaming one of the beans or enabling overriding by setting
spring.main.allow-bean-definition-overriding=true
from this document :
https://spring.io/blog/2022/02/21/spring-security-without-the-websecurityconfigureradapter
they've changed the WebSecurityConfigurerAdapter. so ive changed this :
#Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
return auth.getAuthenticationManager();
}
to this :
#Bean
public void authenticationManagerBuilder(AuthenticationManagerBuilder authConfiguration) throws Exception {
authConfiguration.authenticationProvider(authenticationProvider());
}
and now getting error.
also if i change it to this :
#Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration authConfiguration) throws Exception {
return authConfiguration.getAuthenticationManager();
}
my error goes away?!

How to Control Sequence of Bean Creating and Component Scanning In Spring Boot

Updated
I am Beginner to Spring and I tried to implement spring security application using Java Based Configuration. But now I have to Control sequence of bean creating and component scanning of application.
This is my configuration class
#EnableWebSecurity
#Configuration
class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private UserDetailsService userDetailsService;
#Autowired
public void configureAuthentication(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
authenticationManagerBuilder.userDetailsService(this.userDetailsService).passwordEncoder(passwordEncoder());
}
#Bean
public Md5PasswordEncoder passwordEncoder() {
return new Md5PasswordEncoder();
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.headers().cacheControl();
http.csrf().disable()
.authorizeRequests()
.antMatchers("/authProxy").permitAll()
.antMatchers(HttpMethod.POST,"/login").permitAll()
.anyRequest().authenticated()
.and()
.addFilterBefore(new JWTLoginFilter(authenticationManager()), UsernamePasswordAuthenticationFilter.class)
.addFilterBefore(new JWTAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
}
}
and here is the JWTLoginFilter
public class JWTLoginFilter extends AbstractAuthenticationProcessingFilter {
private TokenAuthenticationService tokenAuthenticationService;
public JWTLoginFilter(AuthenticationManager authenticationManager) {
super(new AntPathRequestMatcher("/login"));
setAuthenticationManager(authenticationManager);
tokenAuthenticationService = new TokenAuthenticationService();
}
#Override
public Authentication attemptAuthentication(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse)
throws AuthenticationException, IOException, ServletException {
AccountCredentials credentials = new ObjectMapper().readValue(httpServletRequest.getInputStream(), AccountCredentials.class);
final Authentication authentication = getAuthenticationManager()
.authenticate(new UsernamePasswordAuthenticationToken(credentials.getUsername(),
credentials.getPassword()));
SecurityContextHolder.getContext().setAuthentication(authentication);
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(credentials.getUsername(), credentials.getPassword());
return getAuthenticationManager().authenticate(token);
}
#Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authentication)
throws IOException, ServletException {
String name = authentication.getName();
tokenAuthenticationService.addAuthentication(response, name);
}
}
This is working fine.
But all thing going wrong When I try to declare JWTLoginFilter as service with #Service annotation and while I am trying to Autowire that.
The Changes that I did as Follows.
this is configuration class.
#EnableWebSecurity
#Configuration
class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private UserDetailsService userDetailsService;
#Autowired
public void configureAuthentication(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
authenticationManagerBuilder.userDetailsService(this.userDetailsService).passwordEncoder(passwordEncoder());
}
#Bean
public Md5PasswordEncoder passwordEncoder() {
return new Md5PasswordEncoder();
}
#Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Autowired
JWTLoginFilter jwtLoginFilter;
#Override
protected void configure(HttpSecurity http) throws Exception {
http.headers().cacheControl();
http.csrf().disable()
.authorizeRequests()
.antMatchers("/authProxy").permitAll()
.antMatchers(HttpMethod.POST,"/login").permitAll()
.anyRequest().authenticated()
.and()
.addFilterBefore(jwtLoginFilter, UsernamePasswordAuthenticationFilter.class)
.addFilterBefore(new JWTAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
}
}
And this is my new JWTLoginFilter
#Service
public class JWTLoginFilter extends AbstractAuthenticationProcessingFilter {
#Autowired
AuthenticationManager authenticationManager;
private TokenAuthenticationService tokenAuthenticationService;
public JWTLoginFilter() {
super(new AntPathRequestMatcher("/login"));
setAuthenticationManager(authenticationManager);
tokenAuthenticationService = new TokenAuthenticationService();
}
#Override
public Authentication attemptAuthentication(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse)
throws AuthenticationException, IOException, ServletException {
AccountCredentials credentials = new ObjectMapper().readValue(httpServletRequest.getInputStream(), AccountCredentials.class);
final Authentication authentication = getAuthenticationManager()
.authenticate(new UsernamePasswordAuthenticationToken(credentials.getUsername(),
credentials.getPassword()));
SecurityContextHolder.getContext().setAuthentication(authentication);
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(credentials.getUsername(), credentials.getPassword());
return getAuthenticationManager().authenticate(token);
}
#Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authentication)
throws IOException, ServletException {
String name = authentication.getName();
tokenAuthenticationService.addAuthentication(response, name);
}
}
This Code gives runtime error called
Error starting Tomcat context. Exception: org.springframework.beans.factory.BeanCreationException. Message: Error creating bean with name 'JWTLoginFilter' defined in file [/media/dilanka/Stuff/CODEBASE/Inspection-Application/Inspection-AuthProxy/target/classes/com/shipxpress/inspection/security/jwt/JWTLoginFilter.class]: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: authenticationManager must be specified
The error is as my thought at the beginning, ComponentScan Scanning and initiating JWTLoginFilter. But at that time AuthenticationManager bean has not created. So It is not auto wiring.
So I have to create AuthenticationManager bean before scanning JWTLoginFilter, But It is not possible because it has to create in class that extended by WebSecurityConfigurerAdapter and spring allows one WebSecurityConfigurerAdapter extended class. So I can't initiate it in another class.
Also
#Override
protected void configure(HttpSecurity http) throws Exception {}
has to declare in WebSecurityConfigurerAdapter extended class and this method use jwtLoginFilter. So all
#Autowired
JWTLoginFilter jwtLoginFilter;
and
#Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
and
#Override
protected void configure(HttpSecurity http) throws Exception {
http.headers().cacheControl();
http.csrf().disable()
.authorizeRequests()
.antMatchers("/authProxy").permitAll()
.antMatchers(HttpMethod.POST,"/login").permitAll()
.anyRequest().authenticated()
.and()
.addFilterBefore(jwtLoginFilter, UsernamePasswordAuthenticationFilter.class)
.addFilterBefore(new JWTAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
}
has to define it in WebSecurityConfig extends WebSecurityConfigurerAdapter class and has to Control sequence of bean creating and component scanning of the application. Does anyone have an idea? please help me.
updated-->
I Tried to implement JWTLoginFilter as follows,
#Service
public class JWTLoginFilter extends AbstractAuthenticationProcessingFilter {
private TokenAuthenticationService tokenAuthenticationService;
#Autowired
public JWTLoginFilter(AuthenticationManager authenticationManager) {
super(new AntPathRequestMatcher("/login"));
}
...
}
But it gives the following error
The dependencies of some of the beans in the application context form a cycle:
┌─────┐
| JWTLoginFilter defined in file [/media/dilanka/Stuff/CODEBASE/Inspection-Application/DR-136812421-dbchangesSendAsMail/Inspection-Application/Inspection-AuthProxy/target/classes/com/shipxpress/inspection/security/jwt/JWTLoginFilter.class]
↑ ↓
| webSecurityConfig (field com.shipxpress.inspection.security.jwt.JWTLoginFilter com.shipxpress.inspection.config.WebSecurityConfig.jwtLoginFilter)
└─────┘
I think the problem is, If we auto wire Constructor as above, Then JWTLoginFilter can't create without creating Configuration beans creating. But Configuration beans needs JWTLoginFilter bean. So it can't create without JWTLoginFilter bean.
Thanks.
#Autowired annotation will be processed after constructor of bean has been called. So your exception does not depend on the sequence of bean creating. If you need to invoke setAuthenticationManager from constructor you can apply #Autowired to the constructor:
#Service
public class JWTLoginFilter extends AbstractAuthenticationProcessingFilter {
AuthenticationManager authenticationManager;
private TokenAuthenticationService tokenAuthenticationService;
#Autowired
public JWTLoginFilter(AuthenticationManager authenticationManager) {
this.authenticationManager = authenticationManager; //if you will need this instance in future
super(new AntPathRequestMatcher("/login"));
setAuthenticationManager(authenticationManager);
tokenAuthenticationService = new TokenAuthenticationService();
}
...
}
Then appropriate bean will be passed to the constructor automatically.
Another solution is to make all initialization in the #PostConstruct method. This method will be called just after #Autowired annotation has been processed:
#Service
public class JWTLoginFilter extends AbstractAuthenticationProcessingFilter {
#Autowired
AuthenticationManager authenticationManager;
private TokenAuthenticationService tokenAuthenticationService;
public JWTLoginFilter(){
super(new AntPathRequestMatcher("/login"));
}
#PostConstruct
public void postConstruct() {
setAuthenticationManager(authenticationManager);
tokenAuthenticationService = new TokenAuthenticationService();
}
...
}
Spring Boot has multiple conditional annotations to use like #ConditionalOnBean to control the sequencing of bean creation
Look into package org.springframework.boot.autoconfigure.condition for all the conditionals available
For the your example, best way is to have constructor injection of AuthenticationManager in JWTLoginFilter

Spring Security authenticationmanager must be specified - for custom filter

I’m trying to create a custom username password authentication filter since I need to validate passwords from two different sources. I’m using Spring Boot 1.2.1 and Java configuration. The error I get when deploying is
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'customUsernamePasswordAuthenticationFilter' defined in file [/Users/rjmilitante/Documents/eclipse-workspace/login-service/bin/com/elsevier/eols/loginservice/CustomUsernamePasswordAuthenticationFilter.class]: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: authenticationManager must be specified
…
Caused by: java.lang.IllegalArgumentException: authenticationManager must be specified
I’m not sure what I’m missing. I have been trying to set authenticationManager for this filter in my SecurityConfig. My code looks like
my filter:
#Component
public class CustomUsernamePasswordAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
public CustomUsernamePasswordAuthenticationFilter(RequestMatcher requiresAuthenticationRequestMatcher) {
super(requiresAuthenticationRequestMatcher);
// TODO Auto-generated constructor stub
}
public CustomUsernamePasswordAuthenticationFilter() {
super(new AntPathRequestMatcher("/login","POST"));
// TODO Auto-generated constructor stub
}
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
throws AuthenticationException {
// String dbValue = request.getParameter("dbParam");
// request.getSession().setAttribute("dbValue", dbValue);
System.out.println("attempting to authentificate");
while (request.getAttributeNames().hasMoreElements()) {
String e = (String) request.getAttributeNames().nextElement();
System.out.println("param name : " + e + " and param value : " + request.getAttribute(e));
}
return null;
}
}
my security config:
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter{
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Bean(name="loginService")
public LoginService loginService(){
return new LoginServiceImpl();
}
#Bean( name="myAuthenticationManager")
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Bean
CustomUsernamePasswordAuthenticationFilter customUsernamePasswordAuthenticationFilter() throws Exception {
CustomUsernamePasswordAuthenticationFilter customUsernamePasswordAuthenticationFilter = new CustomUsernamePasswordAuthenticationFilter();
customUsernamePasswordAuthenticationFilter.setAuthenticationManager(authenticationManagerBean());
return customUsernamePasswordAuthenticationFilter;
}
#Autowired
private myAuthenticationProvider myAuthenticationProvider;
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.anyRequest().authenticated()
.and()
/*.addFilterBefore(customUsernamePasswordAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)*/;
}
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(myAuthenticationProvider);
}
}
Can anyone take a look? not sure what’s up with it.
The documentation for AbstractAuthenticationProcessingFilter states that you must set an AuthenticationManager.
I suggest you try adding the following code inside your CustomUsernamePasswordAuthenticationFilter class:
#Override
#Autowired
public void setAuthenticationManager(AuthenticationManager authenticationManager) {
super.setAuthenticationManager(authenticationManager);
}
I actually got past the error. I just had to remove the #Component annotation from my custom filter.

spring circular dependencies

I have the following configuration:
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled=true)
public class SecurityConfig {
private static final Logger LOGGER = LoggerFactory.getLogger(SecurityConfig.class);
#Resource
private UserDetailsService userDetailsService;
#Resource
private PasswordEncoder passwordEncoder;
.....
#Configuration
#Order(2)
public static class MobileApiSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
#Resource
private UserDetailsService userDetailsService;
#Resource
private PasswordEncoder passwordEncoder;
#Autowired
private CustomBasicAuthenticationFilter customBasicAuthenticationFilter;
#Autowired
private TokenSecurityFilter tokenSecurityFilter;
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.userDetailsService(userDetailsService)
.passwordEncoder(passwordEncoder);
}
protected void configure(HttpSecurity http) throws Exception {
http
.addFilter(customBasicAuthenticationFilter)
.addFilterBefore(tokenSecurityFilter, CustomBasicAuthenticationFilter.class)
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.csrf().disable()
.authorizeRequests()
.antMatchers(Mappings.MOBILE_API + "/**").hasAnyRole(Globals.MOBILE_API_USER_ROLE)
.and()
.exceptionHandling()
.authenticationEntryPoint(new CustomBasicAuthenticationEntryPoint())
.and()
.requestCache()
.requestCache(new NullRequestCache());
}
}
This is my custom filter:
#Component
public class CustomBasicAuthenticationFilter extends BasicAuthenticationFilter {
private static final Logger LOGGER = LoggerFactory.getLogger(CustomBasicAuthenticationFilter.class);
#Autowired
private PrincipalRepository principalRepository;
#Autowired
private AuthenticationCache authenticationCache;
#Autowired
public CustomBasicAuthenticationFilter(AuthenticationManager authenticationManager) {
super(authenticationManager);
}
#Override
protected void onSuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response,
Authentication authResult) throws IOException {
Principal principal = principalRepository.findOne(PrincipalPredicates.userNameEquals(authResult.getName()));
if (principal != null) {
principal.setLastLoginTime(DateTime.now());
principalRepository.save(principal);
} else {
LOGGER.error("Unable to retrieve user " + authResult.getName());
}
authenticationCache.add(authResult, request, response);
super.onSuccessfulAuthentication(request, response, authResult);
}
}
But, when trying to deploy to Tomcat, the following exception is thrown:
Error creating bean with name 'customBasicAuthenticationFilter' defined in file [C:\work\...]: Unsatisfied dependency expressed through constructor argument with index 0 of type [org.springframework.security.authentication.AuthenticationManager]: : No qualifying bean of type [org.springframework.security.authentication.AuthenticationManager] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.security.authentication.AuthenticationManager] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
I am not sure why my filter is looking for an authenticationManager since I am autowiring it. Help is appreciated it.
Updated Question: I added this code to resolve the authenticationManager issue:
#Bean(name="myAuthenticationManager")
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
By adding the above, I am able to get past the authenticationManager issue, but now I am getting this issue:
org.springframework.beans.factory.BeanCreationException:
Could not autowire field: private CustomBasicAuthenticationFilter SecurityConfig$MobileApiSecurityConfigurerAdapter.customBasicAuthenticationFilter;
nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException:
Error creating bean with name 'customBasicAuthenticationFilter':
Requested bean is currently in creation: Is there an unresolvable circular reference?
Thanks
You can try to add #EnableWebSecurity annotation on top of MobileApiSecurityConfigurerAdapter class definition.
I added the #Lazy annotation to the filter and I'm able to deploy now.
Feel free to offer other solutions.

spring-security java config: How to configure Multiple AuthenticationManager instances

I use:
spring boot: 1.1.7
spring-security: 4.0.0.M2
spring-fmk: 4.1.1.RELEASE
Everything is configured with Java Config (including spring-security)
I'm working on a web server project where Authentication: Basic base64Gibberish header are used to authenticate users.
The problem is that depending on the URI the AuthenticationManager is different (because I need 2 different UserDetailsService.
/URI1/** => authManager1
/URI2/** => authManager2
I've tried multiple extensions of WebSecurityConfigurerAdapter with
#Override
#Bean( name = "authManager1" )
public AuthenticationManager authenticationManagerBean() throws Exception
#Override
#Bean( name = "authManager2" )
public AuthenticationManager authenticationManagerBean() throws Exception
to no avail
I always get:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'springSecurityFilterChain'
defined in class path resource [org/springframework/security/config/annotation/web/configuration/WebSecurityConfiguration.class]: Instantiation of bean failed;
nested exception is org.springframework.beans.factory.BeanDefinitionStoreException:
Factory method [public javax.servlet.Filter org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration.springSecurityFilterChain() throws java.lang.Exception]
threw exception; nested exception is java.lang.IllegalArgumentException:
Expecting to only find a single bean for type interface org.springframework.security.authentication.AuthenticationManager,
but found [authManager1, authManager2]
Since I have multiple security filter chains how can I "tell" spring-security to inject different AuthenticationManager in different security filter chains ?
Thanks in advance
P.
You can have multiple http configuration elements, each with its own AuthenticationManager. It could look like that :
#Configuration
#EnableWebSecurity
public class SecurityConfig {
#Bean
private AuthenticationManager authenticationManager1() {
// defines first AuthenticationManager
return authenticationManager;
}
#Bean
private AuthenticationManager authenticationManager2() {
// defines second AuthenticationManager
return authenticationManager;
}
#Configuration
#Order(1)
public static class Uri1ApiConfigurationAdapter extends WebSecurityConfigurerAdapter {
#Autowired
#Qualifier(authenticationManager1)
private authManager1;
#Override
protected AuthenticationManager authenticationManager() {
return authManager1;
}
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/URI1/**")
...
}
}
#Configuration
#Order(2)
public static class Uri2ApiConfigurationAdapter extends WebSecurityConfigurerAdapter {
#Autowired
#Qualifier(authenticationManager2)
private authManager2;
#Override
protected AuthenticationManager authenticationManager() {
return authManager2;
}
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/URI2/**")
...
}
}
}

Resources