首页 文章

Spring引导HTTP Basic传递给JDBC

提问于
浏览
0

我已配置JDBC数据源并自动装配JDBCTemplate以执行自定义SQL查询 . 我也有一个简单的HTTP基本身份验证:

auth.inMemoryAuthentication()
                .withUser("user").password("password").roles("USER");

但是,我想使用用于HTTP Basic的用户和密码来验证数据库本身的用户,即将HTTP Basic的凭据传递给数据源,并以使用HTTP Basic身份验证登录的用户执行查询 . 我在这里面临两个问题,一个是用户名和密码在application.properties文件中,我想在每次用户进行身份验证时覆盖,并且(重新加载?)执行查询作为该用户而不是在用户指定的用户属性文件 .

更新1:

我可以通过编程方式使用如下的用户名和密码:

@Bean
@Primary
public DataSource dataSource() {
    return DataSourceBuilder
        .create()
        .username("")
        .password("")
        .url("")
        .driverClassName("")
        .build();
}

但是每次用户使用这些凭据使用HTTP Basic身份验证时,如何调用此方法?

1 回答

  • 1

    使用 UserCredentialsDataSourceAdapter 作为@ "M. Deinum"建议使用某种过滤器或处理 AuthenticationSuccessEvent .

    基本上你应该用当前主体 usernamepassword 调用 setCredentialsForCurrentThread 方法 .

    您必须禁用身份验证管理器的凭据擦除才能在身份验证后检索用户密码 .

    @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();
        }
    }
    

    数据源适配器:

    @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;
    }
    

    AuthenticationSuccessHandler:

    @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 而不是事件侦听器:

    @Component
    public static class DataSourceCredentialsFilter extends GenericFilterBean {
        private final UserCredentialsDataSourceAdapter dataSourceAdapter;
    
        @Autowired
        public DataSourceCredentialsFilter(UserCredentialsDataSourceAdapter dataSourceAdapter) {
            this.dataSourceAdapter = dataSourceAdapter;
        }
    
        @Override
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
                throws IOException, ServletException {
            final Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            final User user = (User) authentication.getPrincipal();
            dataSourceAdapter.setCredentialsForCurrentThread(user.getUsername(), user.getPassword());
            chain.doFilter(request, response);
            dataSourceAdapter.removeCredentialsFromCurrentThread();
        }
    }
    

    查看完整示例here .

相关问题