Spring boot, spring security override UserDetailsService - spring-security

Working on moving from spring security xml configuration to Java Config in Spring Security.
In my class SecurityConfiguration that extends WebSecurityConfigurerAdapter. However, the problem is that the userDetailsService is not being used by the security filters specifically the UsernamePasswordAuthenticationFilter. I looked at the startup and it seems that this is not created before Spring boots creates the default InMemoryUserDetailsManager.
#Configuration
#EnableWebMvcSecurity
#Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http)
throws Exception {
http.userDetailsService(userDetailsService);
}
}
I have also tried to override the userDetailsServiceBean and userDetailsService in this class using the custom injected ApplicationUserDetailsService.
#Bean(name="myUserDetailsBean")
#Override
public UserDetailsService userDetailsServiceBean() {
return userDetailsService;
}
#Override
public UserDetailsService userDetailsService() {
return userDetailsService;
}
However, when I try to override the authenticationManagerBean it looks like it invokes my configuration before the spring boot configuration initializes but it throws an error (below) that there is a circular reference when initializing the UsernamePasswordAuthenticationFilter. Do I need really need to override the authenticationManagerBean because I need to define what goes into the UsernamePasswordAuthenticationFilter.
#Bean(name="myAuthenticationManager")
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
..
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter]: Circular reference involving containing bean 'securityBeansConfiguration' - consider declaring the factory method as static for independence from its containing instance. Factory method 'usernamePasswordAuthenticationFilter' threw exception; nested exception is java.lang.IllegalArgumentException: successHandler cannot be null
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:189) ~[spring-beans-4.1.4.RELEASE.jar:4.1.4.RELEASE]
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:588) ~[spring-beans-4.1.4.RELEASE.jar:4.1.4.RELEASE]
... 70 common frames omitted
Ideas?

Hi there is simple way to override UserDetailsService
import com.dog.care.domain.User;
import com.dog.care.repository.UserRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import javax.inject.Inject;
import java.util.Optional;
#Component("userDetailsService")
public class UserDetailsService implements org.springframework.security.core.userdetails.UserDetailsService {
private final Logger log = LoggerFactory.getLogger(UserDetailsService.class);
#Inject
private UserRepository userRepository;
#Override
#Transactional
public UserDetails loadUserByUsername(final String login) {
log.debug("Authenticating {}", login);
String lowercaseLogin = login.toLowerCase();
Optional<User> userFromDatabase = userRepository.findOneByLogin(lowercaseLogin);
return userFromDatabase.map(user -> {
if (!user.getActivated()) {
throw new UserNotActivatedException("User " + lowercaseLogin + " was not activated");
}
return new CustomUserDetails(user);
}).orElseThrow(() -> new UsernameNotFoundException("User " + lowercaseLogin + " was not found in the database"));
}
}
This is important: #Component("userDetailsService")
Thanks
Aleksandar

Related

Spring EnableAuthorizationServer with custom AuthenticationManager

I am setting up an OAuth2 + OpenID connect server using Spring security. I have been trying to use the automatic /oauth/token & /oauth/authorize endpoints that are defined when you use the #EnableAuthorizationServer annotation on a class.
#Configuration
#EnableAuthorizationServer
public class AuthServerConfig extends AuthorizationServerConfigurerAdapter{
In the same class, I have autowired an AuthenticationManager to use in configuring the AuthorizationServerEndpointsConfigurer. I have debugged & confirmed that the correct bean is being autowired.
#Autowired
private AuthenticationManager authMan;
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints)
throws Exception{
endpoints
.tokenStore(tokenStore())
.userApprovalHandler(userApprovalHandler())
.authenticationManager(authMan);
}
The problem is, there are two WebSecurityConfigurers being created, the one I defined and what appears to be the default WebSecurityConfigurer. Here is part of the one I defined:
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter{
#Autowired
private UserDetailsSrvc detailsSrvc;
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Bean
public DaoAuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider authProvider
= new DaoAuthenticationProvider();
authProvider.setUserDetailsService(detailsSrvc);
authProvider.setPasswordEncoder(passwordEncoder());
return authProvider;
}
#Autowired
protected void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authenticationProvider());
}
#Override
#Bean(name="myAuthenticationManager")
public AuthenticationManager authenticationManagerBean() throws Exception {
return authenticationManager();
}
Unfortunately, the default is being called when I navigate to localhost:8080/outh/token with my browser. I can tell because my custom UserDetailsService is not being used during the authentication, and because I put a breakpoint on the getWebSecurityConfigurers method in org.springframework.security.config.annotation.web.configuration.AutowiredWebSecurityConfigurersIgnoreParents:
#SuppressWarnings({ "rawtypes", "unchecked" })
public List<SecurityConfigurer<Filter, WebSecurity>> getWebSecurityConfigurers() {
List<SecurityConfigurer<Filter, WebSecurity>> webSecurityConfigurers = new ArrayList<SecurityConfigurer<Filter, WebSecurity>>();
Map<String, WebSecurityConfigurer> beansOfType = beanFactory
.getBeansOfType(WebSecurityConfigurer.class);
for (Entry<String, WebSecurityConfigurer> entry : beansOfType.entrySet()) {
webSecurityConfigurers.add(entry.getValue());
}
return webSecurityConfigurers;
}
The beansOfType map has two entries, but only if I have a class with the #EnableAuthorizationServer annotation. (Only 1 if I comment out annotation)
How do I get my AuthorizationServerConfigurerAdapter (or whatever is actually processing the requests to /oauth/token) to use the WebSecurityConfigurer defined in my WebSecurityConfigurerAdapter? I believe I can get around this issue by defining my own endpoints, and maybe that's the only solution, but I was hoping to utilize the default endpoints.

spring boot spring rabbit: How to create a rabbit template to send a message within a listener

I have a simple listener that is receiving messages from Rabbitmq. I would like to modify the message and publish it to a new exchange/queue. I have been unable to get a rabbit template to work within a listener. Any help would be appreciated. My code is below, when I tried to autowire the template I get
Caused by: java.lang.NullPointerException: null
at com.example.Consumer.onMessage(Consumer.java:27) ~[classes!/:0.0.1-SNAPSHOT]
Classes:
package com.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class RabbittestApplication {
public static void main(String[] args) {
SpringApplication.run(RabbittestApplication.class, args);
}
}
package com.example;
import org.springframework.amqp.core.AcknowledgeMode;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
#Configuration
#EnableAutoConfiguration
public class RabbitConfig {
private static final String SIMPLE_MESSAGE_QUEUE = "qDLX1.dlx";
#Bean
public ConnectionFactory connectionFactory() {
CachingConnectionFactory connectionFactory = new CachingConnectionFactory("RabbitErl19");
connectionFactory.setUsername("gregg");
connectionFactory.setPassword("gregg");
connectionFactory.setPort(5672);
connectionFactory.setVirtualHost("dlxtest");
return connectionFactory;
}
#Bean
public RabbitTemplate rabbitTemplate() {
RabbitTemplate template = new RabbitTemplate(connectionFactory());
return template;
}
#Bean
public SimpleMessageListenerContainer listenerContainer() {
SimpleMessageListenerContainer listenerContainer = new SimpleMessageListenerContainer();
listenerContainer.setConnectionFactory(connectionFactory());
listenerContainer.setQueueNames(SIMPLE_MESSAGE_QUEUE);
listenerContainer.setMessageListener(new Consumer());
listenerContainer.setAcknowledgeMode(AcknowledgeMode.AUTO);
return listenerContainer;
}
}
package com.example;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
#Component
public class Consumer implements MessageListener {
#Autowired
private RabbitTemplate rabbitTemplate;
#Override
public void onMessage(Message message) {
System.out.println("Body: "+new String(message.getBody()));
System.out.println();
message.getMessageProperties().setExpiration("5000");
rabbitTemplate.send("xDLX1.delay", "xq1.retry", message);
}
}
Here is your code:
listenerContainer.setMessageListener(new Consumer());
As you see it is absolutely normal that #Autowired doesn't work. Just because you have bypassed dependency injection.
Since your Consumer is marked with #Component you can simply inject it into that SimpleMessageListenerContainer bean definition:
#Bean
public SimpleMessageListenerContainer listenerContainer(Consumer consumer)
Thanks that did it, I changed my code to what is below and it worked. Your help is much appreciated!
#Autowired
private Consumer consumer;
#Bean
public SimpleMessageListenerContainer listenerContainer() {
SimpleMessageListenerContainer listenerContainer = new SimpleMessageListenerContainer();
listenerContainer.setConnectionFactory(connectionFactory());
listenerContainer.setQueueNames(SIMPLE_MESSAGE_QUEUE);
listenerContainer.setMessageListener(consumer);
listenerContainer.setAcknowledgeMode(AcknowledgeMode.AUTO);
return listenerContainer;
}

How to authorize the menu from web page using the spring boot security sec:authorize-url or using EL expressions?

I'm working on the spring boot security using basic authentication.I have configured basic application security layer and i can authenticate the user.But,now i would like to know how to authorize the user to show only the granted operations without hard coding the role names in client side or server side code using thymeleaf with spring security.
Let's say i have app with some menus in dashboard to show the granted menus to the logged in user.I have read some thymeleaf tutorials by following this link https://github.com/thymeleaf/thymeleaf-extras-springsecurity but i could not get any samples to work using this.
Could anyone help me to know about this scenario ?
import com.triesten.dost.*;
import com.triesten.dost.customUserService.MyCustomUserDetailsService;
import com.triesten.dost.dao.UserDao;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.security.SecurityProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.core.annotation.Order;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.csrf.CsrfFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
#Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
public class ApplicationSecurity extends WebSecurityConfigurerAdapter {
#Autowired
UserDao userDao;
#Autowired
#Qualifier("userDetailsService")
UserDetailsService userDetailsService;
#Autowired
private RESTAuthenticationEntryPoint authenticationEntryPoint;
#Autowired
private RESTAuthenticationFailureHandler authenticationFailureHandler;
#Autowired
private RESTAuthenticationSuccessHandler authenticationSuccessHandler;
/*#Override
public void configure(WebSecurity web) throws Exception {
web
// Spring Security ignores request to static resources such as
// CSS or JS files.
.ignoring().antMatchers("/static/**");
}*/
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/css/**", "/fonts/**", "/images/**");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/", "/index.html", "/login", "/dost/bannerContent").permitAll();
http.authorizeRequests().anyRequest().fullyAuthenticated().and().httpBasic().and().csrf().disable();
http.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint);
http.formLogin().loginPage("/login").loginProcessingUrl("/login/authenticate")
.successHandler(authenticationSuccessHandler);
http.formLogin().failureHandler(authenticationFailureHandler);
http.logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout")).logoutSuccessUrl("/login")
.invalidateHttpSession(true);
http.exceptionHandling().accessDeniedHandler(accessDeniedHandler());
// CSRF tokens handling
http.addFilterAfter(new CsrfTokenResponseHeaderBindingFilter(), CsrfFilter.class);
}
/**
* Configures the authentication manager bean which processes authentication
* requests.
*/
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// Dao based authentication
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
private AccessDeniedHandler accessDeniedHandler() {
return new AccessDeniedHandler() {
#Override
public void handle(HttpServletRequest request, HttpServletResponse response,
AccessDeniedException accessDeniedException) throws IOException, ServletException {
response.getWriter().append("Access denied");
response.setStatus(403);
}
};
}
/**
* This is used to hash the password of the user.
*/
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder(10);
}
/**
* This bean is load the user specific data when form login is used.
*/
#Bean
public UserDetailsService userDetailsService() {
return new MyCustomUserDetailsService(userDao);
}
}
Thanks in advance...

Spring boot using Spring Security authentication failure when using SpringPlainTextPasswordValidationCallbackHandler in an XwsSecurityInterceptor

I have set a up a spring boot (1.2.3) application with spring security and spring-ws. I have configured spring security to use .ldapAuthentication() for authentication in my WebSecurityConfigurerAdapter. I am trying to get the same spring security authenticationManager to authenticate my spring ws SOAP web services using ws-security usernametokens (plain text) in my WsConfigurerAdapter.
I have configured my WebSecurityConfigurerAdapter like this:
package za.co.switchx.config;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.ldap.core.support.LdapContextSource;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Bean
#ConfigurationProperties(prefix="ldap.contextSource")
public LdapContextSource contextSource() {
LdapContextSource contextSource = new LdapContextSource();
return contextSource;
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.ldapAuthentication()
.userSearchBase("cn=Users,dc=SwitchX,dc=co,dc=za")
.userSearchFilter("(uid={0})")
.groupSearchBase("cn=Groups,dc=SwitchX,dc=co,dc=za")
.groupSearchFilter("(&(cn=*)(| (objectclass=groupofUniqueNames)(objectclass=orcldynamicgroup)))")
.contextSource(contextSource());
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/ws/**").permitAll()
.anyRequest().authenticated()
.and()
.csrf().disable()
.httpBasic();
}
}
So then I went to configure my WsConfigurerAdapter like this:
package za.co.switchx.config;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.context.embedded.ServletRegistrationBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.ws.config.annotation.EnableWs;
import org.springframework.ws.config.annotation.WsConfigurerAdapter;
import org.springframework.ws.transport.http.MessageDispatcherServlet;
import org.springframework.ws.wsdl.wsdl11.DefaultWsdl11Definition;
import org.springframework.xml.xsd.SimpleXsdSchema;
import org.springframework.xml.xsd.XsdSchema;
import org.springframework.ws.soap.security.xwss.XwsSecurityInterceptor;
import org.springframework.ws.soap.security.xwss.callback.SpringPlainTextPasswordValidationCallbackHandler;
import org.springframework.ws.server.EndpointInterceptor;
#EnableWs
#Configuration
public class WebServiceConfig extends WsConfigurerAdapter {
#Bean
public ServletRegistrationBean messageDispatcherServlet(ApplicationContext applicationContext) {
MessageDispatcherServlet servlet = new MessageDispatcherServlet();
servlet.setApplicationContext(applicationContext);
servlet.setTransformWsdlLocations(true);
return new ServletRegistrationBean(servlet, "/ws/*");
}
#Bean(name = "ApplicantTypeService")
public DefaultWsdl11Definition defaultWsdl11Definition(XsdSchema applicantTypeServiceSchema) {
DefaultWsdl11Definition wsdl11Definition = new DefaultWsdl11Definition();
wsdl11Definition.setPortTypeName("ApplicantTypePort");
wsdl11Definition.setLocationUri("/ws/ApplicantTypeService");
wsdl11Definition.setTargetNamespace("http://switchx.co.za/services/applicant/types/applicant-type-web-service");
wsdl11Definition.setSchema(applicantTypeServiceSchema);
return wsdl11Definition;
}
#Bean
public XsdSchema applicantTypeSchema() {
return new SimpleXsdSchema(new ClassPathResource("xsd/ApplicantTypeService.xsd"));
}
#Bean
public XwsSecurityInterceptor securityInterceptor() {
XwsSecurityInterceptor securityInterceptor = new XwsSecurityInterceptor();
securityInterceptor.setCallbackHandler(new SpringPlainTextPasswordValidationCallbackHandler());
securityInterceptor.setPolicyConfiguration(new ClassPathResource("securityPolicy.xml"));
return securityInterceptor;
}
#Override
public void addInterceptors(List<EndpointInterceptor> interceptors) {
interceptors.add(securityInterceptor());
}
}
If I use a SimplePasswordValidationCallbackHandler in the XwsSecurityInterceptor it does authenticate the ws usernametoken correctly, so I know there is nothing wrong with the ws-security section. And if I logon via http basic it authenticates my ldap user correctly so I know that works.
The problem is that when I try use my ldap user logon in the ws security usernametoken I get ERROR c.s.xml.wss.logging.impl.filter - WSS1408: UsernameToken Authentication Failed in the logs, so looks like its not using my global ldap authentication defined in the WebSecurityConfigAdapter
I cant seem to figure out how to get the SpringPlainTextPasswordValidationCallbackHandler (which is supposed to use spring security) in the XwsSecurityInterceptor to use the global authenticationManager, please help?? I have really been bashing my head against this for the last day but cant seem to win.
Ok I figured this out so though I would post for anyone trying this in the future.
I resolved this problem by changing my spring boot class to:
#SpringBootApplication
#EnableGlobalMethodSecurity(securedEnabled = true)
public class SwitchxApplication extends WebMvcConfigurerAdapter {
#SuppressWarnings("unused")
private static final Logger log = LoggerFactory.getLogger(SwitchxApplication.class);
#Bean
public ApplicationSecurity applicationSecurity() {
return new ApplicationSecurity();
}
#Configuration
#Order(Ordered.HIGHEST_PRECEDENCE)
protected static class AuthenticationConfiguration extends GlobalAuthenticationConfigurerAdapter {
#Bean
#ConfigurationProperties(prefix="ldap.contextSource")
public LdapContextSource contextSource() {
LdapContextSource contextSource = new LdapContextSource();
return contextSource;
}
#Override
public void init(AuthenticationManagerBuilder auth) throws Exception {
auth
.ldapAuthentication()
.userSearchBase("cn=Users,dc=Blah,dc=co,dc=za")
.userSearchFilter("(uid={0})")
.groupSearchBase("cn=Groups,dc=Blah,dc=co,dc=za")
.groupSearchFilter("(&(cn=*)(|(objectclass=groupofUniqueNames)(objectclass=orcldynamicgroup)))")
.contextSource(contextSource());
}
}
#Order(Ordered.LOWEST_PRECEDENCE - 8)
protected static class ApplicationSecurity extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/ws/**").permitAll()
.anyRequest().authenticated()
.and()
.csrf().disable()
.httpBasic();
}
}
public static void main(String[] args) {
SpringApplication.run(SwitchxApplication.class, args);
}
}
And then made the following relevant changes in my WsConfigurerAdapter to:
#EnableWs
#Configuration
public class WebServiceConfig extends WsConfigurerAdapter {
private static final Logger log = LoggerFactory.getLogger(WebServiceConfig.class);
#Autowired
private AuthenticationManager authenticationManager;
#Bean
public ServletRegistrationBean messageDispatcherServlet(ApplicationContext applicationContext) {
MessageDispatcherServlet servlet = new MessageDispatcherServlet();
servlet.setApplicationContext(applicationContext);
servlet.setTransformWsdlLocations(true);
return new ServletRegistrationBean(servlet, "/ws/*");
}
.....
.....
#Bean
public SpringPlainTextPasswordValidationCallbackHandler callbackHandler() {
SpringPlainTextPasswordValidationCallbackHandler callbackHandler = new SpringPlainTextPasswordValidationCallbackHandler();
try {
callbackHandler.setAuthenticationManager(authenticationManager);
} catch(Exception e) {
log.error(e.getMessage());
}
return callbackHandler;
}
#Bean
public XwsSecurityInterceptor securityInterceptor() {
XwsSecurityInterceptor securityInterceptor = new XwsSecurityInterceptor();
securityInterceptor.setCallbackHandler(callbackHandler());
securityInterceptor.setPolicyConfiguration(new ClassPathResource("securityPolicy.xml"));
return securityInterceptor;
}
#Override
public void addInterceptors(List<EndpointInterceptor> interceptors) {
interceptors.add(securityInterceptor());
}
}
So basically the end result is that for all /ws paths the basic http security is ignored but because of the security intercepter in the WS Config it will use a basic ws-security user name token to authenticate web service calls, allowing you to have both authentication mechanisms using spring security set up with ldap.
I hope this helps someone, was a bit tricky not finding of lot of documentation on the boot and java config documentation on this particular setup and stuff as it still relatively new. But after not getting this working, its pretty awesome and Im very impressed.

DataSourceInitializer : ApplicationEventMulticaster is not initialized

I am using Spring Boot 1.2.0 with embedded h2database.
The database is initialized using schema.sql file in the classpath.
It worked fine until I added #EnableGlobalMethodSecurity annotation to the WebSecurityConfiguration class.
java.lang.IllegalStateException: ApplicationEventMulticaster not initialized exception is thrown from DataSourceInitializer.runSchemaScripts
What may be the problem ?
Here is the code:
#Configuration
#ComponentScan
#EnableAutoConfiguration
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
#EnableGlobalMethodSecurity(securedEnabled = true)
#Configuration
class WebSecurityConfiguration extends GlobalAuthenticationConfigurerAdapter {
#Autowired
DataSource dataSource;
#Override
public void init(AuthenticationManagerBuilder auth) throws Exception {
auth.jdbcAuthentication().dataSource(dataSource);
}
}
I think the solution is to not use the init method to setup JDBC authentication. Try with a separate class that extends GlobalAuthenticationConfigurerAdapter and override the config method.

Resources