springspring-bootspring-securitybcryptuserdetailsservice

Default admin user in config and other users from database


I'm using spring boot with spring security and jpa. I would like to have admin user in config and other users in database. The problem is when I added UserDetailsService, the admin user from application.properties stop working.

application.properties:

spring.security.user.name=admin
spring.security.user.password={bcrypt}$2a$10$7F7xGm8iuzafFA7RPS8gzeKJm9qNBwtejT4hSuBKXMNlc/4NxOy1G
spring.security.user.roles=admin

Spring Security config class:

@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Qualifier("myUserDetailsService")
    @Autowired
    private UserDetailsService userDetailsService;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(encodePWD());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .csrf().disable()
                .authorizeRequests()
                .requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll()
                .antMatchers("/").permitAll()
                .antMatchers("/uzytkownik/pacjent/rejestracja").anonymous()
                .anyRequest().hasRole("admin")
                .and().formLogin().permitAll()
                ;


    }

    @Bean
    public BCryptPasswordEncoder encodePWD() {
        return new BCryptPasswordEncoder();
    }

}

Solution

  • Without any configuration Spring Security reads user from properties file by default. But if you add an UserDetailsService it means you want to read users using the interface's method loadUserByUsername. This method can be implemented for example to read users from database

    If you want your admin user from application.properties to be considered as a user, you can create it in your implementation of UserDetailsService :

    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.security.core.userdetails.User;
    import org.springframework.security.core.userdetails.UserDetails;
    import org.springframework.security.core.userdetails.UserDetailsService;
    import org.springframework.security.core.userdetails.UsernameNotFoundException;
    import org.springframework.stereotype.Service;
    
    @Service
    public class MyUserDetailsService implements UserDetailsService {
    
        @Value("${spring.security.user.name}")
        private String adminUserName;
    
        @Value("${spring.security.user.password}")
        private String adminPassword;
    
        @Value("${spring.security.user.roles}")
        private String adminRole;
    
        @Override
        public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
            if(username.equals(adminPassword)) {
                return User.builder().username(adminUserName).password(adminPassword).roles(adminRole).build();
            }
    
            //return your other users from database here
            return null;
        }
    }