英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论