How to configure datasource when using authenticationProvider in spring boot security?

Viewed 218

If I am using jdbcAuthentication, it will be auth.jdbcAuthentication().dataSource(datasource);

Now I have two databases, one for app and one for security.

I can not find a way configure which database to be used by using authenticationProvider()

@Autowired
@Qualifier("securityDataSource")
private DataSource securityDataSource;

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {

    // use jdbc authentication ... oh yeah!!!       
    auth.jdbcAuthentication().dataSource(securityDataSource);
    auth.authenticationProvider(authenticationProvider());
    
}

 @Bean
public DaoAuthenticationProvider authenticationProvider() {
    DaoAuthenticationProvider auth = new DaoAuthenticationProvider();
    auth.setUserDetailsService(userService); //set the custom user details service
    auth.setPasswordEncoder(passwordEncoder()); //set the password encoder - bcrypt
    return auth;
}

How I solved the problem

@Configuration
@EnableJpaRepositories(basePackages={"${spring.data.jpa.security.repository.packages}"}, 
                       entityManagerFactoryRef = "securityEntityManagerFactory")
public class DemoSecurityDataSourceConfig {

    @Bean
    @ConfigurationProperties(prefix="security.datasource")
    public DataSource securityDataSource() {
        return DataSourceBuilder.create().build();
    }
    
    @Bean
    @ConfigurationProperties(prefix="spring.data.jpa.security")
    public LocalContainerEntityManagerFactoryBean securityEntityManagerFactory(EntityManagerFactoryBuilder builder, @Qualifier("securityDataSource") DataSource securityDataSource) {
        return builder
                .dataSource(securityDataSource)
                .build();
    }   
}
@Configuration
@EnableJpaRepositories(basePackages={"${spring.data.jpa.app.repository.packages}"},
                       entityManagerFactoryRef = "appEntityManagerFactory")
public class DemoAppDataSourceConfig {
    
    @Primary
    @Bean
    @ConfigurationProperties(prefix="app.datasource")
    public DataSource appDataSource() {
        return DataSourceBuilder.create().build();
    }
    
    @Primary
    @Bean
    @ConfigurationProperties(prefix="spring.data.jpa.app")
    public LocalContainerEntityManagerFactoryBean appEntityManagerFactory(EntityManagerFactoryBuilder builder, DataSource appDataSource) {
        return builder
                .dataSource(appDataSource)
                .build();
    }
}
1 Answers

You can configure your DataSources programatically and then use the JdbcUserDetailsManager to configure which one should be used by Spring Security.

In the example below, there are 2 DataSources, one using H2 and one using MySQL.

Spring Security uses the H2 DataSource since we have added the "security" @Qualifier.

@Bean("security")
public DataSource securityDataSource() {
    return new EmbeddedDatabaseBuilder()
            .setType(EmbeddedDatabaseType.H2)
            .addScript("classpath:org/springframework/security/core/userdetails/jdbc/users.ddl")
            .build();
}

@Bean
@Primary
public DataSource primaryDataSource() {
    DataSourceBuilder dataSourceBuilder = DataSourceBuilder.create();
    dataSourceBuilder.url("jdbc:mysql://localhost:3306/db_example");
    dataSourceBuilder.username("springuser");
    dataSourceBuilder.password("ThePassword");
    return dataSourceBuilder.build();
}

@Bean
UserDetailsManager users(@Qualifier("security") DataSource dataSource) {
    UserDetails user = User.builder()
            .username("user")
            .password("{bcrypt}$2a$10$GRLdNijSQMUvl/au9ofL.eDwmoohzzS7.rmNSJZ.0FxO/BTk76klW")
            .roles("USER")
            .build();
    JdbcUserDetailsManager users = new JdbcUserDetailsManager(dataSource);
    users.createUser(user);
    return users;
}
Related