我已配置JDBC数据源并自动装配JDBCTemplate以执行自定义SQL查询。我还有一个简单的HTTP基本身份验证:
auth.inMemoryAuthentication()
.withUser("user").password("password").roles("USER");
但是,我想使用用于HTTP Basic的用户和密码来验证数据库本身的用户,即将HTTP Basic的凭据传递给数据源,并以登录的用户身份执行查询HTTP基本身份验证。我在这里面临两个问题,一个是用户名和密码在application.properties文件中,我想在每次用户进行身份验证时覆盖,并且(重新加载?)执行查询作为该用户而不是指定的用户在属性文件中。
更新1:
我可以通过编程方式使用如下的用户名和密码:
@Bean
@Primary
public DataSource dataSource() {
return DataSourceBuilder
.create()
.username("")
.password("")
.url("")
.driverClassName("")
.build();
}
但是,每当用户使用带有这些凭据的HTTP Basic身份验证进行日志记录时,如何调用此方法?
答案 0 :(得分:1)
使用vcd
作为@“M.Deinum”建议使用某种过滤器或处理UserCredentialsDataSourceAdapter
。
基本上,您应该使用当前主体AuthenticationSuccessEvent
和setCredentialsForCurrentThread
调用username
方法。
您必须禁用身份验证管理器的凭据擦除才能在身份验证后检索用户密码。
password
数据源适配器:
@EnableWebSecurity
public static class Security extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.eraseCredentials(false) // for password retrieving
.inMemoryAuthentication()
.withUser("postgres").password("postgres1").roles("USER");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.httpBasic().and().authorizeRequests().mvcMatchers("/").fullyAuthenticated();
}
}
AuthenticationSuccessHandler:
@Bean
public UserCredentialsDataSourceAdapter dataSource(DataSourceProperties properties) {
final UserCredentialsDataSourceAdapter dataSourceAdapter = new UserCredentialsDataSourceAdapter();
dataSourceAdapter.setTargetDataSource(DataSourceBuilder.create()
.driverClassName(properties.getDriverClassName())
.url(properties.getUrl())
.username(properties.getUsername())
.password(properties.getPassword())
.type(SimpleDriverDataSource.class) // disable pooling
.build());
((SimpleDriverDataSource) dataSourceAdapter.getTargetDataSource()).setDriverClass(org.postgresql.Driver.class); //binder won't set it automatically
return dataSourceAdapter;
}
或者您可以使用@Component
public static class AuthenticationHandler /*implements ApplicationListener<AuthenticationSuccessEvent> use that if your spring version is less than 4.2*/ {
private final UserCredentialsDataSourceAdapter dataSourceAdapter;
@Autowired
public AuthenticationHandler(UserCredentialsDataSourceAdapter dataSourceAdapter) {
this.dataSourceAdapter = dataSourceAdapter;
}
@EventListener(classes = AuthenticationSuccessEvent.class)
public void authenticationSuccess(AuthenticationSuccessEvent event) {
final Authentication authentication = event.getAuthentication();
final User user = (User) authentication.getPrincipal();
dataSourceAdapter.setCredentialsForCurrentThread(user.getUsername(), user.getPassword()); // <- the most important part
}
}
代替事件监听器:
Filter
请参阅完整示例here。