Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Enabling WebSecurityConfigurer via @Profile does not work

I have, what I think is, a very simple and basic setup for locally running a Spring Boot webapp with some authentication.

I would expect that when I run this application through Spring Boot, that my custom security settings would override the default behavior when I specify the local profile.

mvn -Dspring.profiles.active="local" spring-boot:run

Maybe I'm specifying the profiles.active wrong, but when the app runs, it still spits out a generated password to use, and doesn't seem to allow any access to the /login path without said authentication.

I'm also not seeing the active profiles under /env either, which may be a little telling.

I have a WebSecurityConfigurer overridden like so:

@Configuration
@EnableWebSecurity
@Profile("local")
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().anyRequest().fullyAuthenticated().and().formLogin().permitAll();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication().withUser("admin").password("admin").roles("ADMIN", "USER")
        .and().withUser("user").password("user").roles("USER");

    }
}

My main @Configuration class is your standard Spring Java-style base config:

@Configuration
@ComponentScan
@EnableAutoConfiguration
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
like image 589
bvulaj Avatar asked Jul 18 '14 14:07

bvulaj


People also ask

Is Spring Security enabled by default?

If Spring Security is on the classpath, then web applications are secured by default. Spring Boot relies on Spring Security's content-negotiation strategy to determine whether to use httpBasic or formLogin .

How do I configure AuthenticationManagerBuilder?

Step 1: Add the security jar or dependency in your application. Step 2: Create a security config class and extend the WebSecurityConfigurerAdapter class. Step 3: Add the annotation @EnableWebSecurity on top of the class. Step 4: For authentication, override the method configure(AuthenticationManagerBuilder auth) .


2 Answers

I think I ran into the same issue. I wanted to use Spring profiles to select between none, basic, form, etc. auth. However, if I put the @Profile, @Configuration, and @EnableWebMvcSecurity on the public class WebSecurityConfig extends WebSecurityConfigurerAdapter class, like they show in the examples, basic auth was active at times when I wanted no auth. (This is with @SpringBootApplication on my Application class.

I achieved what I wanted with making beans out of WebSecurityConfigurerAdapter, instead of @Configurations (code snippet is in Groovy):

@Configuration
@EnableWebMvcSecurity
class SecurityConfig {
    @Bean
    @Profile('no-auth')
    WebSecurityConfigurerAdapter noAuth() {
        new WebSecurityConfigurerAdapter() {
            @Override
            void configure(HttpSecurity http) throws Exception {
                http.authorizeRequests().anyRequest().permitAll()
            }
        }
    }

    @Bean
    @Profile('default')
    WebSecurityConfigurerAdapter basic() {
        new WebSecurityConfigurerAdapter() {
            @Override
            void configure(HttpSecurity http) throws Exception {
                http
                    .authorizeRequests()
                        .antMatchers('/').permitAll()
                        .anyRequest().authenticated()
                        .and()
                    .httpBasic()
            }

            @Override
            public void configure(AuthenticationManagerBuilder auth) throws Exception {
                auth
                    .inMemoryAuthentication()
                        .withUser("user").password("password").roles("USER");
            }
        }
    }
}
like image 53
Courtney Faulkner Avatar answered Nov 04 '22 07:11

Courtney Faulkner


Second attempt to provide better control of security settings. What's the high level options for controlling security auto configuration:

  • Switch off security completely and permanently:
    • remove Spring Security from the classpath
    • or exlude security auto config - @EnableAutoConfiguration(exclude = SecurityAutoConfiguration.class)
  • Switch off default basic auth security by setting security.basic.enabled=false

It is pretty easy to control different security settings if you have a total control of how security settings, security auto configuration and spring profiles are used.

@Configuration
@ComponentScan
public class Application {
    public static void main(String[] args) throws Throwable {
        SpringApplication.run(Application.class, args);
    }
}

@Configuration
public class WebSecurityConfig {

    @Configuration
    @EnableAutoConfiguration(exclude = SecurityAutoConfiguration.class)
    @ConditionalOnExpression("!${my.security.enabled:false}")
    protected static class DefaultWebSecurityConfig {
    }

    @Configuration
    @EnableAutoConfiguration
    @EnableWebMvcSecurity
    @Profile("local")
    @ConditionalOnExpression("${my.security.enabled:false}")
    protected static class LocalWebSecurityConfig extends WebSecurityConfigurerAdapter {
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http
                .authorizeRequests()
                    .antMatchers("/", "/home").permitAll()
                    .anyRequest().authenticated();
            http
                .formLogin().loginPage("/login").permitAll().and()
                .logout().permitAll();
        }

        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            auth
                .inMemoryAuthentication()
                    .withUser("user").password("password").roles("USER");
        }
    }

}

In above classes I basically removed @EnableAutoConfiguration from Application class order to use it conditionally. Created two config classes, DefaultWebSecurityConfig and LocalWebSecurityConfig which are chosen by my.security.enabled flag using a Boot @ConditionalOnExpression.

First config simply excludes SecurityAutoConfiguration if my security is not enabled. Second one enabled security and uses local profile. By creating yet another config with a different profile you can control what happens with different profiles. Then you could choose if security is enabled and which profile is used:

#java -jar build/libs/gs-securing-web-0.1.0.jar
#java -jar build/libs/gs-securing-web-0.1.0.jar --spring.profiles.active=local --my.security.enabled=true

If you have an option to use application.yml, different settings could be automatically applied per profile still defining a default values. This would be good if you just want to disable default basic authentication enabled by default security auto config.

security:
    basic:
        enabled: false
---
spring:
    profiles: local
security:
    basic:
        enabled: true
---

There are probably a million different ways to do these and it's always case by case which works best for current use case.

like image 34
Janne Valkealahti Avatar answered Nov 04 '22 07:11

Janne Valkealahti