Define basic-security users, passwords and roles in application.yml

10,470

It can be achieved with custom ConfigurationProperties:

@ConfigurationProperties("application")
public class ApplicationClients {

    private final List<ApplicationClient> clients = new ArrayList<>();

    public List<ApplicationClient> getClients() {
        return this.clients;
    }

}

@Getter
@Setter
public class ApplicationClient {
    private String username;
    private String password;
    private String[] roles;
}

@Configuration
@EnableConfigurationProperties(ApplicationClients.class)
public class AuthenticationManagerConfig extends
        GlobalAuthenticationConfigurerAdapter {

    @Autowired
    ApplicationClients application;

    @Override
    public void init(AuthenticationManagerBuilder auth) throws Exception {
        for (ApplicationClient client : application.getClients()) {
            auth.inMemoryAuthentication()
                    .withUser(client.getUsername()).password(client.getPassword()).roles(client.getRoles());
        }
    }

}

and then you can specify the users in your application.yml:

application:
  clients:
    - username: rw
      password: rw
      roles: READ,WRITE
    - username: r
      password: r
      roles: READ
    - username: w
      password: w
      roles: WRITE

don't forget to add spring-boot-configuration-processor to your build.gradle:

compile 'org.springframework.boot:spring-boot-configuration-processor'

Update April 2018

For Spring Boot 2.0, I use the following class:

@Configuration
@EnableGlobalMethodSecurity(securedEnabled = true)
@EnableWebSecurity
@ConditionalOnWebApplication
@EnableConfigurationProperties(ApplicationClients.class)
@RequiredArgsConstructor
@Slf4j
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    private final ApplicationClients application;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable()
            .authorizeRequests()
            .requestMatchers(EndpointRequest.to("health")).permitAll()
            .requestMatchers(EndpointRequest.toAnyEndpoint()).hasRole("ACTUATOR")
            .antMatchers("/rest/**").authenticated()
            .antMatchers("/soap/**").authenticated()
            .and()
            .cors()
            .and()
            .httpBasic();
    }

    @Bean
    public InMemoryUserDetailsManager inMemoryUserDetailsManager() {
        final InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
        log.info("Importing {} clients:", application.getClients().size());

        application.getClients().forEach(client -> {
            manager.createUser(User.withDefaultPasswordEncoder()
                .username(client.getUsername())
                .password(client.getPassword())
                .roles(client.getRoles())
                .build());
            log.info("Imported client {}", client.toString());
        });

        return manager;
    }
}

Please keep in mind that User.withDefaultPasswordEncoder() is marked deprecated because of security-concerns.

Share:
10,470
user3105453
Author by

user3105453

Updated on June 21, 2022

Comments

  • user3105453
    user3105453 almost 2 years

    I am looking for a way to secure methods with the @Secured annotation of Spring Boot. For about 10-15 users, I wouldn't want to connect to a database and obtain the users and their authorities/roles from there but rather store them locally in the profile-specific application.yml file. Is there a concept in Spring Boot supporting this idea? All I could find so far works with the basic security actuator ('org.springframework.boot:spring-boot-starter-security') and looks like this:

    security:
      basic:
        enabled: true
      user:
        name: admin
        password: admin
        role: EXAMPLE
    

    However, I'm still able to access a method annotated with @RolesAllowed("READ") even though I would assume that user admin shouldn't have access to said method. My SecurityConfiguration looks like this:

    @Configuration
    @EnableWebSecurity
    @EnableGlobalMethodSecurity(jsr250Enabled = true)
    @Profile("secure")
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.authorizeRequests()
                    .anyRequest()
                    .fullyAuthenticated()
                    .and()
                    .httpBasic();
    
            http.sessionManagement()
                    .sessionFixation()
                    .newSession();
    
            http.csrf().disable();
            http.headers().frameOptions().disable();
    
        }
    }
    

    Eventually this might be a different issue but maybe it's important for my own understanding.

    I'm wondering how I could specify multiple users with different passwords and different roles in my application.yml and annotate methods to ensure only authorized users can access the methods.