I use spring boot 2 + Spring Security 5. I don't want to erase credentials after authentication, so I want to set eraseCredentialsAfterAuthentication = false in ProviderManger. But I don't know how to configure it in Spring Boot without XML configuration.
Okay, I know it. Just configure in WebSecurityConfigurerAdapter.
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.eraseCredentials(false);
}
}
Related
I am new to JPA and Spring Boot.
http://www.baeldung.com/spring-security-registration-password-encoding-bcrypt
I'm looking to encode the password -- where would I place this bean -- do I just define it in my application.properties or in the pom.xml
Also you can define in your #Configuration beans, but is recommend to define password encoder in your ##EnableWebSecurity beans, it is automatically add #Configuration annotation for you and you can config more security related things.
#EnableWebSecurity
public class YourWebConfiguration extends WebSecurityConfigurerAdapter {
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(new BCryptPasswordEncoder());
}
}
I'm working on a Spring project. The functionality is already done. What's missing is the security context.
As my project (maven) is separated in different sub projects (Services, RestControllers, Domain), I want the security configuration to be a separate sub project as well, which I only have to add as dependency to the main app to activate it.
I started with a very basic configuration, which is, by now, the only class in the security sub project:
#Configuration
#EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("admin")
.password("admin1")
.roles("ADMIN", "USER");
}
#Override
public void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
http.authorizeRequests().antMatchers("/").permitAll().and().authorizeRequests().anyRequest().authenticated();
}
}
As soon as I add this project as dependency to my main app, the security context is obviously getting activated, as the default spring login dialogue pops up. The thing is, that Spring ignores the configuration which I've defined in the SecurityConfiguration. It even won't let me access '/', or neither it let's me login with the defined user. Checking in debug mode, it never runs through the public void configure(AuthenticationManagerBuilder auth) method.
In a nut shell:
It activates the spring security context, but it does not apply my configuration. Why is that?
In case of Spring MVC project with Java based configuration import SecurityConfiguration to your ApplicationConfiguration
#EnableWebMvc
#Configuration
#ComponentScan({"xx.xxx.xx.*"})
#PropertySource("classpath:xxx.properties")
#Import(value = {SecurityConfiguration.class}) // <= like this
public class ApplicationConfiguration extends WebMvcConfigurerAdapter { ... }
You may also need SecurityInitializer. This class has to be present even though it's empty. This is a good place for certain filters that must be executed before security configuration.
import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;
public class SecurityInitializer extends AbstractSecurityWebApplicationInitializer { }
I tried disabling all actuator endpoints for production environment in application.yml configuration file:
endpoints.enabled: false
It works for all endpoints except for /info.
How can I turn off all endpoints for given environment?
UPDATE:
Project I am working on is also acting as Eureka client.
In documentation for Spring Cloud Netflix in section Status Page and Health Indicator (http://cloud.spring.io/spring-cloud-netflix/spring-cloud-netflix.html) it says that "Eureka instance default to "/info" and "/health" respectively".
Is there any solution to disable those endpoints?
I was able to disable /health endpoint with endpoints.enabled: false, but not the /info endpoint.
Finally I managed to solve my problem. I enabled only /info and /health endpoints in actuator. And to allow access to /info endpoint only to users with role ADMIN I needed to mix actuator management security and spring security configuration.
So my application.yml looks like this:
endpoints.enabled: false
endpoints:
info.enabled: true
health.enabled: true
management.security.role: ADMIN
And spring security configuration like this (where I needed to change order of ManagementSecurityConfig to have higher priority):
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfiguration {
#Configuration
protected static class AuthenticationSecurity extends GlobalAuthenticationConfigurerAdapter {
#Autowired
private AuthenticationProvider authenticationProvider;
public AuthenticationSecurity() {
super();
}
#Override
public void init(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("admin").password("secret").roles("ADMIN");
}
}
#Configuration
#Order(Ordered.HIGHEST_PRECEDENCE + 2)
public static class ManagementSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.requestMatchers()
.antMatchers("/info/**")
.and()
.authorizeRequests()
.anyRequest().hasRole("ADMIN")
.and()
.httpBasic();
}
}
#Configuration
public static class ApiWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
// API security configuration
}
}
}
Your sample configuration looks suspicious to me. I guess you meant
endpoints:
enabled: true
In any case, I just tried to add this to a vanilla Spring Boot app (using 1.3.1 and all endpoints were disabled (as expected).
I try to translate the following websecurity configuration written in Java to a plain-yml configuration.
#Order(Ordered.HIGHEST_PRECEDENCE)
#Configuration
#EnableWebMvcSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private UserDetailsService userDetailsService;
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/register/**").permitAll()
.anyRequest().authenticated().and().csrf().disable()
.httpBasic();
}
#Autowired
public void registerAuthentication(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
}
}
This is the security relevant part of my application.yml:
security:
require_ssl: true
basic:
enabled: true
enable_csrf: false
ignored:
- /register/**
When I use the yml-version the endpoints are not accessible without authentication, but also valid users are not permitted to access the site. I think it's because I am using a custom userDetailsService which is not recognised.
How can I define the same behaviour of the registerAuthentication-method part with the yml-version? Is there a security.userDetailsServiceClass property or something similar?
On application properties reference there is nothing related to UserDetailsService, so must be not supported,also it's a advanced condiguration which can be done by normal configuration. Boot provides via properties only simple configuration to get start quickly, like httpBasic, you can combine both, but note your
ignored:
- /register/**
are clashing with Java Config's matchers
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);
}
}
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:
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.
maven will spawn a new process to run a boot app and it doesn't inherit your -Dspring.profiles.active="local" which you passed to mvn command itself.
Why don't you just build the boot fat jar and then run it manually as an executable jar and then you can control what command line parameters you pass to your program.
Other than that, Spring Boot reference doc mentions in a security chapter:
If Spring Security is on the classpath then web applications will be secure by default with “basic” authentication on all HTTP endpoints.
So I just tried this with Securing a Web Application Guide and if I added what you wrote in your question, app defaults to basic authentication when using a profile which is not active.
#EnableAutoConfiguration allows you to define excludes for autoconfiguration classes, but you need to find a way to disable this together with a profile. So possibly wrapping #EnableAutoConfiguration in two different #Configuration classes enabled by different profiles so that other would exclude security auto-configuration.
What we do (in more sophisticated way) in framework itself is a usage of #Conditional which provides better way to enable/disable parts of auto-configuration.