@ -16,20 +16,26 @@
package org.springframework.boot.autoconfigure.security ;
package org.springframework.boot.autoconfigure.security ;
import java.util.LinkedHashSet ;
import java.util.List ;
import java.util.List ;
import java.util.Set ;
import org.apache.commons.logging.Log ;
import org.apache.commons.logging.LogFactory ;
import org.springframework.beans.factory.annotation.Autowired ;
import org.springframework.beans.factory.annotation.Autowired ;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean ;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean ;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean ;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean ;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication ;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication ;
import org.springframework.boot.autoconfigure.security.SecurityProperties.User ;
import org.springframework.context.annotation.Configuration ;
import org.springframework.context.annotation.Configuration ;
import org.springframework.core.Ordered ;
import org.springframework.core.Ordered ;
import org.springframework.core.annotation.Order ;
import org.springframework.core.annotation.Order ;
import org.springframework.security.authentication.AuthenticationManager ;
import org.springframework.security.authentication.AuthenticationManager ;
import org.springframework.security.authentication.AuthenticationProvider ;
import org.springframework.security.config.annotation.ObjectPostProcessor ;
import org.springframework.security.config.annotation.ObjectPostProcessor ;
import org.springframework.security.config.annotation.SecurityConfigurer ;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder ;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder ;
import org.springframework.security.config.annotation.web.WebSecurityConfigurer ;
import org.springframework.security.config.annotation.authentication.configurers.GlobalAuthenticationConfigurerAdapter ;
import org.springframework.security.config.annotation.web.builders.WebSecurity ;
/ * *
/ * *
* Configuration for a Spring Security in - memory { @link AuthenticationManager } .
* Configuration for a Spring Security in - memory { @link AuthenticationManager } .
@ -41,26 +47,77 @@ import org.springframework.security.config.annotation.web.builders.WebSecurity;
@ConditionalOnMissingBean ( AuthenticationManager . class )
@ConditionalOnMissingBean ( AuthenticationManager . class )
@ConditionalOnWebApplication
@ConditionalOnWebApplication
@Order ( Ordered . LOWEST_PRECEDENCE - 3 )
@Order ( Ordered . LOWEST_PRECEDENCE - 3 )
public class AuthenticationManagerConfiguration implements
public class AuthenticationManagerConfiguration extends GlobalAuthenticationConfigurerAdapter {
WebSecurityConfigurer < WebSecurity > {
@Autowired
private static Log logger = LogFactory . getLog ( AuthenticationManagerConfiguration . class ) ;
private SecurityProperties security ;
@Autowired
@Autowired
private List < SecurityPrequisite > dependencies ;
private List < SecurityPrequisite > dependencies ;
@Override
@Autowired
public void init ( WebSecurity builder ) throws Exception {
private ObjectPostProcessor < Object > objectPostProcessor ;
}
@Override
public void configure ( WebSecurity builder ) throws Exception {
}
@Autowired
@Autowired
public void authentication ( AuthenticationManagerBuilder builder ) throws Exception {
private SecurityProperties security ;
SecurityAutoConfiguration . authentication ( builder , this . security ) ;
public void init ( AuthenticationManagerBuilder auth ) throws Exception {
auth . apply ( new BootDefaultingAuthenticationConfigurerAdapter ( ) ) ;
}
}
}
/ * *
* We must add { @link BootDefaultingAuthenticationConfigurerAdapter } in the
* init phase of the last { @link GlobalAuthenticationConfigurerAdapter } . The
* reason is that the typical flow is something like :
*
* < ul >
* < li > A
* { @link GlobalAuthenticationConfigurerAdapter # init ( AuthenticationManagerBuilder ) }
* exists that adds a { @link SecurityConfigurer } to the
* { @link AuthenticationManagerBuilder } < / li >
* < li >
* { @link AuthenticationManagerConfiguration # init ( AuthenticationManagerBuilder ) }
* adds BootDefaultingAuthenticationConfigurerAdapter so it is after the
* { @link SecurityConfigurer } in the first step < / li >
* < li > We then can default an { @link AuthenticationProvider } if necessary .
* Note we can only invoke the
* { @link AuthenticationManagerBuilder # authenticationProvider ( AuthenticationProvider ) }
* method since all other methods add a { @link SecurityConfigurer } which is
* not allowed in the configure stage . It is not allowed because we
* guarantee all init methods are invoked before configure , which cannot be
* guaranteed at this point . < / li >
* < / ul >
*
* @author Rob Winch
* /
private class BootDefaultingAuthenticationConfigurerAdapter extends GlobalAuthenticationConfigurerAdapter {
@Override
public void configure ( AuthenticationManagerBuilder auth )
throws Exception {
if ( auth . isConfigured ( ) ) {
return ;
}
User user = AuthenticationManagerConfiguration . this . security . getUser ( ) ;
if ( user . isDefaultPassword ( ) ) {
logger . info ( "\n\nUsing default password for application endpoints: "
+ user . getPassword ( ) + "\n\n" ) ;
}
AuthenticationManagerBuilder defaultAuth = new AuthenticationManagerBuilder ( objectPostProcessor ) ;
Set < String > roles = new LinkedHashSet < String > ( user . getRole ( ) ) ;
AuthenticationManager parent = defaultAuth .
inMemoryAuthentication ( )
. withUser ( user . getName ( ) )
. password ( user . getPassword ( ) )
. roles ( roles . toArray ( new String [ roles . size ( ) ] ) )
. and ( )
. and ( )
. build ( ) ;
auth . parentAuthenticationManager ( parent ) ;
}
}
}