4

I am currently building a restful API (with Spring Boot) that accesses a database. This application will eventually be hosted on a server.

What I would like to do:

  1. Configure the database with multiple users, and assign them different rights to different tables
  2. Depending on which endpoint is called, use a specific user to execute that queries within that function

How do I go about configuring the application above?

The answers I've found so far involve configuring multiple datasources, but for the above application, there is only one datasource, but multiple users.

I have read the following link but am still trying to understand it

https://kimrudolph.de/blog/spring-datasource-routing

Do I configure multiple datasources all with the same URL (jdbcURL in this case), and multiple sets of usernames and passwords for each role?

Thank you!

1
  • 1
    Regarding your question: Yes, I would do so. Commented Oct 28, 2019 at 12:00

1 Answer 1

2

You have already found the best way to do that task, I mean AbstractRoutingDataSource. If you have fixed number of users it is the simplest way you could use following approach:

public final class RoutingDataSource extends AbstractRoutingDataSource {
    @Override
    protected Object determineCurrentLookupKey() {
        return UserContextHolder.getUserName() + "DataSource";
    }
}

And configuration:

@Bean
@Qualifier("user1DataSource")
public DataSource userOneDataSource() {
    return DataSourceBuilder.create()
            .username("user1")
            .password("pass")
             ...
             .build();
}

@Bean
@Qualifier("user2DataSource")
public DataSource userOneDataSource() {
    return DataSourceBuilder.create()
            .username("user2")
             ...
             .build();
}

@Bean
@Primary
public RoutingDataSource dataSource(Map<String, DataSource> datasources) {
    return new RoutingDataSource().dataSource(datasources);
 }

If you need add users and datasources at runtime you could use somethig like this:

public final class RoutingDataSource extends AbstractRoutingDataSource {
    private final ConcurrentHashMap<String, DataSource> dynamicDataSources = new ConcurrentHashMap<>();

    @Override
    protected Object determineCurrentLookupKey() {
        return UserContextHolder.getUserName() + "_datasource";
    }

    @Override
    protected DataSource determineTargetDataSource() {
        String currentLookupKey = this.determineCurrentLookupKey().toString();
        String userName = UserContextHolder.getUserName();
        String password = UserContextHolder.getPassword();

        return this.dynamicDataSources.computeIfAbsent(currentLookupKey, (key) -> DataSourceBuilder.create()
                .driverClassName("your.driver.class")
                .url("jdbc:same:url/here")
                .username(userName)
                .password(password)
                .build());
    }
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.