How to initialize Spring Boot security config with

2020-05-06 14:26发布

问题:

Following the topical guide here and adding a BCrypt password encoder based on Baeldung's example here I have configured my Spring Boot application to use my database (set up separately, not auto-generated by an ORM or something) as its source of user details for authentication. This part of my security configuration (here) looks like this:

@Override
public void configure(AuthenticationManagerBuilder builder) throws Exception {
    builder .jdbcAuthentication()
            .dataSource(dataSource)
            .withUser(User.withUsername("admin").password(passwordEncoder().encode("pass")).roles("SUPER"));
    logger.debug("Configured app to use JDBC authentication with default database.");
}

@Bean
public PasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder();
}

On the first run, this works, creating a user called 'admin' with a hashed password and the specified role in the database. (This is a PostgreSQL database for what it's worth.) However, if I try to run the app again, it fails to start, crashing because it tried to create the same user again and got a duplicate primary key error.

What I'd like: I'd like Spring Boot to create the default user if it doesn't already exist, skip over it if one already exists.

Why: It is necessary to be able to log in to a newly initialized copy of the application, sometimes restarting several times, for testing and for experimentation on the developer's machine. My "production" database should already have an 'admin' login and the app should not overwrite it, or crash because it cannot.

My question, therefore, is: How can I initialize a default user in Spring Boot's jdbcAuthentication configuration in such a way that Spring Boot won't crash if the username already exists?

Alternatively: If I could INSERT a default user into the database with SQL when the database is spun up, I wouldn't need to do it in the Spring Boot configuration. But I don't know how to hash a password in an INSERT statement in a way that matches Spring Boot's hashing.

PS: I have another issue with my new configuration breaking some automated test classes (see the other question if interested).

回答1:

You can use the alternative solution that you have thought using the option .withDefaultSchema() with the jdbcauthentication that you are using. As you have mentioned in that alternative that you may have to figure out way to use hashed password in that script.

Should you have any followup question, this baeldung blog post will help you.

https://www.baeldung.com/spring-security-jdbc-authentication

Hope this helps.