Here's my application class.
#SpringBootApplication
#ComponentScan({"org.app.genesis.client.controller","org.app.genesis.commons.service",
"org.app.genesis.commons.security","org.app.genesis.inventory.service","org.app.genesis.client.auth"})
#EnableJpaRepositories(basePackages = "org.app.genesis.*.repo")
#EntityScan(basePackages = "org.app.genesis.*.model")
public class Application extends SpringBootServletInitializer {
public static void main(String[] args) {
ApplicationContext ctx = SpringApplication.run(Application.class, args);
}
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
..other configs here
#Configuration
#EnableWebSecurity
#ComponentScan({"org.app.genesis.client.auth"})
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private AuthenticationProvider customAuthProvider;
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(customAuthProvider);
}
}
}
However whenever I build the app. it always throw this exception
[ERROR] Failed to execute goal org.springframework.boot:spring-boot-maven-plugin:1.2.3.RELEASE:run (default-cli) on project app-client-webapp: An exception occured while running. null:
InvocationTargetException: Unable to start embedded container; nested exception is org.springframework.boot.context.embedded.EmbeddedServletContainerException: Unable to start embedded Tomcat: Error creating bean with name 'org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire method: public void `org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration.setFilterChainProxySecurityConfigurer(org.springframework.security.config.annotation.ObjectPostProcessor,java.util.List) throws java.lang.Exception; nested exception is org.springframework.beans.factory.BeanExpressionException: Expression parsing failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.app.genesis.client.Application$SecurityConfig': Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.app`enter code here`.genesis.client.Application$SecurityConfig$$EnhancerBySpringCGLIB$$b49171d7]: No default constructor found; nested exception is java.lang.NoSuchMethodException: org.app.genesis.client.Application$SecurityConfig$$EnhancerBySpringCGLIB$$b49171d7.<init>() -> [Help 1]`
EDIT: New Spring Security Config
#Configuration
#EnableWebSecurity
#Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
protected static class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
#Qualifier("customAuthenticationProvider")
private AuthenticationProvider customAuthProvider;
#Override
protected void configure(AuthenticationManagerBuilder auth){
auth.authenticationProvider(customAuthProvider);
}
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Override
public void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests().anyRequest().authenticated();
http
.formLogin().failureUrl("/login?error")
.defaultSuccessUrl("/dashboard")
.loginPage("/login")
.permitAll()
.and()
.logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout")).logoutSuccessUrl("/login")
.permitAll().and().csrf().disable();
}
}
Complete code is missing because of which I can't pin point the line which is causing this issue but I will definitely make an attempt to explain it, so that you can fix it yourself
#EnableWebSecurity
The JavaDoc documentaion:
Add this annotation to an #Configuration class to have the Spring
Security configuration defined in any WebSecurityConfigurer or more
likely by extending the WebSecurityConfigurerAdapter base class and
overriding individual methods.
It seems like either you missed to override "configure" method of WebSecurityConfigurerAdapter base class or didn't implemented the "configureGlobal" method correctly or you may want to create a class extends AbstractSecurityWebApplicationInitializer, it will load the springSecurityFilterChain automatically.
However I suggest you to go through the following sources and you should be able to figure out what is that you are missing.
https://github.com/spring-projects/spring-security-oauth-javaconfig/blob/master/samples/oauth2-sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/SecurityConfiguration.java
http://www.mkyong.com/spring-security/spring-security-hello-world-annotation-example/
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 9 days ago.
Improve this question
I'm trying to upgrade Spring Security from 5.8 to 6.0. Here's the old version of the WebSecurityConfig class:
#Configuration
#ImportResource( "classpath:spring-ui-security-config.xml" )
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
DaoAuthenticationProvider daoAuthenticationProvider;
#Override
protected void configure( AuthenticationManagerBuilder auth ) {
auth.authenticationProvider( daoAuthenticationProvider );
}
#Override
protected void configure( HttpSecurity http ) throws Exception {
http
.requiresChannel()
.anyRequest()
.requiresSecure();
}
}
And the new version:
#Configuration
#ImportResource( "classpath:spring-ui-security-config.xml" )
#EnableWebSecurity
public class WebSecurityConfig {
#Autowired
DaoAuthenticationProvider daoAuthenticationProvider;
#Bean
public SecurityFilterChain securityFilterChain( HttpSecurity http ) throws Exception {
http
.requiresChannel()
.anyRequest()
.requiresSecure()
.and()
.authenticationProvider( daoAuthenticationProvider );
return http.build();
}
}
When I try to run the app, I get the following 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 'securityFilterChain' defined in class path resource [path/WebSecurityConfig.class]: Unsatisfied dependency expressed through method 'securityFilterChain' 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.IllegalArgumentException: Found 5 beans for type interface org.springframework.security.authentication.AuthenticationManager, but none marked as primary
Hi i'm new to spring boot and trying implement the security to my rest apis.
i'm using spring boot 2.0.7.release
i have configures my WebSecurityConfig as following
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Resource(name = "userService")
private UserDetailsService userDetailsService;
#Bean
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Autowired
public void globalUserDetails(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService)
.passwordEncoder(encoder());
}
#Bean
public JwtAuthenticationFilter authenticationTokenFilterBean() throws Exception {
return new JwtAuthenticationFilter();
}
#Bean
public PasswordEncoder encoder(){
PasswordEncoder encoder = new CustomPasswordEncoder();
return encoder;
}
....
}
I have add the resource name so that i can point the to custom userDetailsService.
I have tried configuring authenticationManager Bean by came and pointing the bean by Qualifier authenticationManager bean still it the error remains same.
my pom.xml looks like for security
......
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
......
and my implemented UserServiceImpl is
#Service(value = "userService")
public class UserServiceImpl implements UserService, UserDetailsService {
#Autowired
private UserDAOService userDao;
#Autowired
private AuthenticationManager authenticationManager;
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userDao.findByUsername(username);
if(user == null){
throw new UsernameNotFoundException("Invalid username or password.");
}
return new org.springframework.security.core.userdetails.User(user.getEmail(), user.getPassword(), getAuthority());
}
#Override
public String login(LoginUser user) {
// valid user if it exits then do the following
authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword()));
//generate the token and do other process.
}
following are the error logs. i have provided only mail errors
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'webSecurityConfig': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'userService': Unsatisfied dependency expressed through field 'authenticationManager'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.security.authenticationManager' defined in class path resource [com/saikrishna/security/config/WebSecurityConfig.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.security.authentication.AuthenticationManager]: Circular reference involving containing bean 'webSecurityConfig' - consider declaring the factory method as static for independence from its containing instance. Factory method 'authenticationManagerBean' threw exception; nested exception is java.lang.IllegalArgumentException: delegateBuilder cannot be null
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'userService': Unsatisfied dependency expressed through field 'authenticationManager'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.security.authenticationManager' defined in class path resource [com/saikrishna/security/config/WebSecurityConfig.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.security.authentication.AuthenticationManager]: Circular reference involving containing bean 'webSecurityConfig' - consider declaring the factory method as static for independence from its containing instance. Factory method 'authenticationManagerBean' threw exception; nested exception is java.lang.IllegalArgumentException: delegateBuilder cannot be null
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.security.authenticationManager' defined in class path resource [com/saikrishna/security/config/WebSecurityConfig.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.security.authentication.AuthenticationManager]: Circular reference involving containing bean 'webSecurityConfig' - consider declaring the factory method as static for independence from its containing instance. Factory method 'authenticationManagerBean' threw exception; nested exception is java.lang.IllegalArgumentException: delegateBuilder cannot be null
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.security.authentication.AuthenticationManager]: Circular reference involving containing bean 'webSecurityConfig' - consider declaring the factory method as static for independence from its containing instance. Factory method 'authenticationManagerBean' threw exception; nested exception is java.lang.IllegalArgumentException: delegateBuilder cannot be null
Caused by: java.lang.IllegalArgumentException: delegateBuilder cannot be null
at org.springframework.util.Assert.notNull(Assert.java:193) ~[spring-core-5.0.11.RELEASE.jar:5.0.11.RELEASE]
In order to help you better, it is better if you indicate which reference you are following to implement JWT mechansim.
Conceptually, this part of the source code is wrong:
#Override
public String login(LoginUser user) {
// valid user if it exits then do the following
authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword()));
//generate the token and do other process.
}
See if the modifications below can help you
1) Consider using Java Config to declare your beans, in a seperate Configuration class
#Configuration
public class ServiceConfig{
#Bean
protected UserDAOService daoService()
{
return new UserDAOServiceImpl();
}
#Bean
protected UserDetailsService userDetailService( UserDAOService dao )
{
return new UserServiceImpl( dao );
}
#Bean
public PasswordEncoder encoder(){
PasswordEncoder encoder = new CustomPasswordEncoder();
return encoder;
}
#Bean
public JwtAuthenticationFilter authenticationTokenFilterBean() throws Exception{ {
return new JwtAuthenticationFilter();
}
}
2) Modification to your WebSecurityConfig
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private UserDetailsService userDetailsService;
#Autowired
private PasswordEncoder passwordEncoder;
#Override
protected void configure( AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService( userDetailsService ).passwordEncoder( passwordEncoder );
}
}
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'authorizationServerConfig': Unsatisfied
dependency expressed through field 'authenticationManager'; nested
exception is
org.springframework.beans.factory.NoSuchBeanDefinitionException: No
qualifying bean of type
'org.springframework.security.authentication.AuthenticationManager'
available: expected at least 1 bean which qualifies as autowire
candidate. Dependency annotations:
{#org.springframework.beans.factory.annotation.Autowired(required=true)}
Hi I have spring-boot web app and I'm trying to implement login/authorization -authentication system using Spring Security and OAuth2 by following this example: https://www.youtube.com/watch?v=dTAgI_UsqMg&t=1307s
Every thing was good but when I run my application I get exception saying it can+t find bean for AuthenticationManager even thought it is there and autowired.
Looking across internet this seems like a know or common issue with Oauth2 but I can't find right workaround
Some people suggested to "expose" the AuthenticationManager bean, I'm not sure what that means in this context
This is link to my current project on github: https://github.com/chenchi13/spring-boot-cms
Can anyone help me figure this out?
class that is throwing exception:
#EnableResourceServer
#Configuration
public class ResourceServerConfig extends WebSecurityConfigurerAdapter {
#Autowired
private AuthenticationManager authenticationManager;
#Autowired
private UserDetailsService customUserDetailService;
#Override
protected void configure(HttpSecurity http) throws Exception {
http.requestMatchers()
.antMatchers("/login", "/oauth/authorize")
.and()
.authorizeRequests()
.anyRequest()
.authenticated()
.and()
.formLogin()
.permitAll();
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//auth.parentAuthenticationManager(authenticationManager)
// .inMemoryAuthentication()
// .withUser("Peter")
// .password("peter")
// .roles("USER");
auth.parentAuthenticationManager(authenticationManager)
.userDetailsService(customUserDetailService);
}
}
Authorization Server Config:
#Configuration
#EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
#Autowired
private AuthenticationManager authenticationManager;
#Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security.tokenKeyAccess("permitAll()")
.checkTokenAccess("isAuthenticated()");
}
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients
.inMemory()
.withClient("ClientId")
.secret("secret")
.authorizedGrantTypes("authorization_code")
.scopes("user_info")
.autoApprove(true);
}
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationManager);
}
}
Remove the following from ResourceServerConfig:
#Autowired
private AuthenticationManager authenticationManager;
And change configure method like following:
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(customUserDetailService);
}
Also override the following method in ResourceServerConfig:
#Override
#Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
This should fix your issue.
I think you are missing definition for authenticationManager bean. I am adding the lines below, check it out once:
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
// Other Details
#Bean
#Override
protected AuthenticationManager authenticationManager() throws Exception {
return super.authenticationManager();
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService)
.passwordEncoder(new ShaPasswordEncoder(encodingStrength));
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.httpBasic()
.realmName(securityRealm)
.and()
.csrf()
.disable();
}
// Other Details
}
You can go through reference link below.
Reference: Spring Boot with JWT and OAuth2.0
Hope this helps you :)
I am new to spring and trying to create a web app using spring boot and jsp which I can deploy using tomcat8 on a raspberry pi. I can deploy my app through sts on an embedded tomcat instance and I can also deploy a war file to Jenkins without any errors. However, when I add the war to tomcat8 webapps folder and start tomcat I get the following error:
2016-04-19 10:54:41.384 WARN 5525 --- [ost-startStop-1] ationConfigEmbeddedWebApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire method: public void com.rcctv.controllers.UserController.setUserService(com.rcctv.services.UserService); nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'userServiceImpl' defined in file [/usr/share/tomcat8/webapps/RaspberryCCTV-0.0.1-SNAPSHOT/WEB-INF/classes/com/rcctv/services/UserServiceImpl.class]: Unsatisfied dependency expressed through constructor argument with index 1 of type [org.springframework.security.crypto.password.PasswordEncoder]: : Error creating bean with name 'webSecurityConfig': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'userServiceImpl': Requested bean is currently in creation: Is there an unresolvable circular reference?; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'webSecurityConfig': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'userServiceImpl': Requested bean is currently in creation: Is there an unresolvable circular reference?
I have tried annotating my configuration class with #Lazy and added setter methods to my userServiceImpl class but I still got the issue. Any help would be greatly appreciated?
webConfig class
#Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Value("${rememberMe.privateKey}")
private String rememberMeKey;
#Value("${spring.profiles.active}")
private String env;
#Resource
private UserDetailsService userService;
#Bean
public HibernateJpaSessionFactoryBean sessionFactory() {
return new HibernateJpaSessionFactoryBean();
}
#Bean
public RememberMeServices rememberMeServices() {
TokenBasedRememberMeServices rememberMeServices = new TokenBasedRememberMeServices(rememberMeKey, userService);
return rememberMeServices;
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Bean
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/",
"/home",
"/error",
"/signup",
"/forgot-password",
"/reset-password/*",
"/public/**",
"/users/*").permitAll()
.anyRequest().authenticated();
http
.formLogin()
.loginPage("/login")
.defaultSuccessUrl("/raspberrycctv")
.permitAll().and()
.rememberMe().key(rememberMeKey).rememberMeServices(rememberMeServices()).and()
.logout()
.permitAll();
if (!env.equals("dev"))
http.requiresChannel().anyRequest().requiresSecure();
}
#Autowired
#Override
protected void configure(AuthenticationManagerBuilder authManagerBuilder) throws Exception {
authManagerBuilder.userDetailsService(userService).passwordEncoder(passwordEncoder());
}
}
UserSeviceImpl
#Service
#Transactional(propagation=Propagation.SUPPORTS, readOnly=true)
public class UserServiceImpl implements UserService, UserDetailsService {
private static final Logger logger = LoggerFactory.getLogger(UserServiceImpl.class);
private UserRepository userRepository;
private PasswordEncoder passwordEncoder;
private MailSender mailSender;
#Autowired
public UserServiceImpl(UserRepository userRepository,
PasswordEncoder passwordEncoder,
MailSender mailSender) {
this.mailSender = mailSender;
this.userRepository = userRepository;
this.passwordEncoder = passwordEncoder;
}
#Autowired
public void setUserRepository(UserRepository userRepository) {
this.userRepository = userRepository;
}
#Autowired
public void setPasswordEncoder(PasswordEncoder passwordEncoder) {
this.passwordEncoder = passwordEncoder;
}
#Autowired
public void setMailSender(MailSender mailSender) {
this.mailSender = mailSender;
}
#Override
#Transactional(propagation=Propagation.REQUIRED, readOnly=false)
public void signup(SignupForm signupForm) {
final User user = new User();
user.setEmail(signupForm.getEmail());
user.setName(signupForm.getName());
user.setPassword(passwordEncoder.encode(signupForm.getPassword()));
user.getRoles().add(Role.UNVERIFIED);
user.setVerificationCode(RandomStringUtils.randomAlphanumeric(16));
userRepository.save(user);
TransactionSynchronizationManager.registerSynchronization(
new TransactionSynchronizationAdapter() {
#Override
public void afterCommit() {
try {
String verifyLink = Utilities.hostUrl() + "/users/" + user.getVerificationCode() + "/verify";
mailSender.send(user.getEmail(), Utilities.getMessage("verifySubject"), Utilities.getMessage("verifyEmail", verifyLink));
logger.info("Verification mail to " + user.getEmail() + " queued.");
} catch (MessagingException e) {
logger.error(ExceptionUtils.getStackTrace(e));
}
}
});
}
}
I think you should go through Spring Reference about IoC container.
WebSecurityConfig class requires UserDetailsService, which is implemented by UserServiceImpl. Also, UserServiceImpl requires PasswordEncoder which is provided by WebSecurityConfig. This causes a circular reference. Removing constructor injection should be enough to resolve your problem.
Side note: Try not to use constructor injection. Spring is clever when it comes to DI, but if you use constructor injection you are forcing spring to use your way. This can also cause circular reference errors.
I recommend you to at least skim this article: https://steveschols.wordpress.com/2012/06/05/i-was-wrong-constructor-vs-setter-injection/
I am having some issues getting my application set up using method level annotation controlled by #EnableGlobalMethodSecurity I am using Servlet 3.0 style initialization using
public class SecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer {
public SecurityWebApplicationInitializer() {
super(MultiSecurityConfig.class);
}
}
I have attempted 2 different ways of initialising an AuthenticationManager both with their own issues. Please note that not using #EnableGlobalMethodSecurity results in a successful server start up and all of the form security executes as expected. My issues arise when I add #EnableGlobalMethodSecurity and #PreAuthorize("hasRole('ROLE_USER')") annotations on my controller.
I am attempting to set up form-based and api-based security independently. The method based annotations need only work for the api security.
One configuration was the following.
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled=true)
public class MultiSecurityConfig {
#Configuration
#Order(1)
public static class ApiWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http.antMatcher("/api/**").httpBasic();
}
protected void registerAuthentication(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("user").password("password").roles("USER").and()
.withUser("admin").password("password").roles("USER", "ADMIN");
}
}
#Configuration
public static class FormWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/static/**","/status");
}
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().hasRole("USER").and()
.formLogin().loginPage("/login").permitAll();
}
protected void registerAuthentication(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("user").password("password").roles("USER").and()
.withUser("admin").password("password").roles("USER", "ADMIN");
}
}
}
This is not ideal as I really want only a single registration of the authentication mechanism but the main issue is that it results in the following exception:
java.lang.IllegalArgumentException: Expecting to only find a single bean for type interface org.springframework.security.authentication.AuthenticationManager, but found []
As far as I am aware #EnableGlobalMethodSecurity sets up its own AuthenticationManager so I'm not sure what the problem is here.
The second configuration is as follows.
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled=true)
public class MultiSecurityConfig {
#Bean
protected AuthenticationManager authenticationManager() throws Exception {
return new AuthenticationManagerBuilder(ObjectPostProcessor.QUIESCENT_POSTPROCESSOR)
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER").and()
.withUser("admin").password("password").roles("USER", "ADMIN").and()
.and()
.build();
}
#Configuration
#Order(1)
public static class ApiWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
#Override protected void configure(HttpSecurity http) throws Exception {
http.antMatcher("/api/**").httpBasic();
}
}
#Configuration
public static class FormWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/static/**","/status");
}
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().hasRole("USER").and()
.formLogin().loginPage("/login").permitAll();
}
}
}
This config actually starts successfully but with an exception
java.lang.IllegalArgumentException: A parent AuthenticationManager or a list of AuthenticationProviders is required
at org.springframework.security.authentication.ProviderManager.checkState(ProviderManager.java:117)
at org.springframework.security.authentication.ProviderManager.<init>(ProviderManager.java:106)
at org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder.performBuild(AuthenticationManagerBuilder.java:221)
and when I test I found that the security doesn't work.
I've been looking at this for a couple of days now and even after diving into spring security implementation code I can't seem to find what is wrong with my configuration.
I am using spring-security-3.2.0.RC1 and spring-framework-3.2.3.RELEASE.
When you use the protected registerAuthentication methods on WebSecurityConfigurerAdapter it is scoping the Authentication to that WebSecurityConfigurerAdapter so EnableGlobalMethodSecurity cannot find it. If you think about this...it makes sense since the method is protected.
The error you are seeing is actually a debug statement (note the level is DEBUG). The reason is that Spring Security will try a few different ways to automatically wire the Global Method Security. Specifically EnableGlobalMethodSecurity will try the following ways to try and get the AuthenticationManager:
If you extend GlobalMethodSecurityConfiguration and override the registerAuthentication it will use the AuthenticationManagerBuilder that was passed in. This allows for isolating the AuthenticationManager in the same way you can do so with WebSecurityConfigurerAdapter
Try to build from the global shared instance of AuthenticationManagerBuilder, if it fails it logs the error message you are seeing (Note the logs also state "This is ok for now, we will try using an AuthenticationManager directly")
Try to use an AuthenticationManager that is exposed as a bean.
For your code, you are going to be best off using something like the following:
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled=true)
public class MultiSecurityConfig {
// Since MultiSecurityConfig does not extend GlobalMethodSecurityConfiguration and
// define an AuthenticationManager, it will try using the globally defined
// AuthenticationManagerBuilder to create one
// The #Enable*Security annotations create a global AuthenticationManagerBuilder
// that can optionally be used for creating an AuthenticationManager that is shared
// The key to using it is to use the #Autowired annotation
#Autowired
public void registerSharedAuthentication(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER").and()
.withUser("admin").password("password").roles("USER", "ADMIN");
}
#Configuration
#Order(1)
public static class ApiWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
// Since we didn't specify an AuthenticationManager for this class,
// the global instance is used
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/api/**")
.httpBasic();
}
}
#Configuration
public static class FormWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
// Since we didn't specify an AuthenticationManager for this class,
// the global instance is used
public void configure(WebSecurity web) throws Exception {
web
.ignoring()
.antMatchers("/static/**","/status");
}
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().hasRole("USER")
.and()
.formLogin()
.loginPage("/login")
.permitAll();
}
}
}
NOTE: More documentation around this will be getting added to the reference in the coming days.