Spring Data. 在运行时更改数据库用户凭据

huangapple go评论65阅读模式
英文:

Spring Data. Change DB user credentials at runtime

问题

有一个Spring Boot应用程序。用于与数据库进行分叉,我使用Spring Data(JPA + Repository)。

是否有办法根据API用户请求更改数据源的数据库用户凭据?我的意思是每个MVC请求必须使用自己的数据库用户凭据进行自己的工作。

我已经阅读了关于AbstractRoutingDataSource的信息。但是有一个限制:在DataSourceMap中无法在运行时添加数据源。

实际上,我想使用Apache PerUserPoolDataSource,并更改数据库用户凭据(使用Spring Security Context获取用户信息)。

英文:

There is Spring Boot Aplication. For forking with DB I use Spring Data (JPA + Repository).

Is there way to change DB user-credentials for datasource per API user-request? I mean each MVC request must do his own work with exactly his DB user-credentials.

I've read info about AbstractRoutingDataSource. But there is limitation: there isn't possibility to add datasource at runtime in DataSourceMap.

In fact I want to use apache PerUserPoolDataSource and change DB user-credentials (using Spring Security Context to get user information)

答案1

得分: 2

我已经找到解决方案。首先,需要定义自定义数据源配置。

@Bean
public UserCredentialsDataSourceAdapter dataSource() throws ClassNotFoundException {
    final UserCredentialsDataSourceAdapter dataSourceAdapter = new UserCredentialsDataSourceAdapter();
    dataSourceAdapter.setTargetDataSource(perUserPoolDataSource());
    return dataSourceAdapter;
}

private PerUserPoolDataSource perUserPoolDataSource() throws ClassNotFoundException {
    DriverAdapterCPDS driverAdapter = new DriverAdapterCPDS();
    driverAdapter.setDriver(properties.getDriverClassName());
    driverAdapter.setUrl(properties.getUrl());
    driverAdapter.setUser(properties.getUsername());//default
    driverAdapter.setPassword(properties.getPassword());//default
    driverAdapter.setAccessToUnderlyingConnectionAllowed(true);

    PerUserPoolDataSource dataSource = new PerUserPoolDataSource();
    dataSource.setConnectionPoolDataSource(driverAdapter);

    return dataSource;
}

正如你所看到的,这里使用了来自Apache的基本数据源:PerUserPoolDataSource。同时,我将使用UserCredentialsDataSourceAdapter作为主要数据源。

然后,需要编写自定义过滤器,用于为成功认证的用户更改用户凭据:

dataSourceAdapter.setCredentialsForCurrentThread(user.getUsername(), user.getPassword());

这个解决方案适用于阻塞范式(非响应式)。具有特定用户凭据的一个线程将执行所有查询。

英文:

I've found solution. First of all need to define custom datasource configuration.

@Bean
    public UserCredentialsDataSourceAdapter dataSource() throws ClassNotFoundException {
        final UserCredentialsDataSourceAdapter dataSourceAdapter = new UserCredentialsDataSourceAdapter();
        dataSourceAdapter.setTargetDataSource(perUserPoolDataSource());
        return dataSourceAdapter;
    }

    private PerUserPoolDataSource perUserPoolDataSource() throws ClassNotFoundException {
        DriverAdapterCPDS driverAdapter = new DriverAdapterCPDS();
        driverAdapter.setDriver(properties.getDriverClassName());
        driverAdapter.setUrl(properties.getUrl());
        driverAdapter.setUser(properties.getUsername());//default
        driverAdapter.setPassword(properties.getPassword());//default
        driverAdapter.setAccessToUnderlyingConnectionAllowed(true);

        PerUserPoolDataSource dataSource = new PerUserPoolDataSource();
        dataSource.setConnectionPoolDataSource(driverAdapter);

        return dataSource;
    }

As you see - there is base datasource from Apache: PerUserPoolDataSource.
Also as main datasource I will use UserCredentialsDataSourceAdapter.

Then need to write custom filter, which will change user credentials for successefully authenticated users:

dataSourceAdapter.setCredentialsForCurrentThread(user.getUsername(), user.getPassword());

This solution works for blocked paradygm (not reactive). One thread with credentials for specific user will do all queries.

huangapple
  • 本文由 发表于 2020年9月15日 23:09:43
  • 转载请务必保留本文链接:https://go.coder-hub.com/63904771.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定