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);
}
}
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 .
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) .
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");
}
}
}
}
Second attempt to provide better control of security settings. What's the high level options for controlling security auto configuration:
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With