首页 > 解决方案 > Spring Boot Oauth2 从错误的数据源加载客户端详细信息

问题描述

我有一个使用多个数据源的 Spring Boot 应用程序:

@RequiredArgsConstructor
@Configuration
@AutoConfigureAfter({ DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class })
public class FlywayCustomConfig {

    @Resource(name = "dataSource")
    private final DataSource gameDatasource;

    @Resource(name = "profileDataSource")
    private final DataSource profileDataSource;

    @Resource(name = "authDataSource")
    private final DataSource authDataSource;

    /**
     * Primary Flyway bean. Used for the game database. This database is being wiped clean after every game.
     *
     * @return Flyway bean
     */
    @Primary
    @Bean(name = "flyway")
    @ConfigurationProperties(prefix = "flyway.game")
    public Flyway flywayGame() {
        Flyway flyway = Flyway.configure()
                .locations("classpath:db/migration/game")
                .dataSource(gameDatasource)
                .load();
        flyway.migrate();
        return flyway;
    }

    /**
     * Profile Flyway bean. Used for the profile database. This database is persistent and should not change.
     *
     * @return Flyway bean
     */
    @Bean(name = "flywayProfile")
    @ConfigurationProperties(prefix = "flyway.profile")
    public Flyway flywayProfile() {
        Flyway flyway = Flyway.configure()
                .locations("classpath:db/migration/profile")
                .dataSource(profileDataSource)
                .load();
        flyway.migrate();
        return flyway;
    }

    /**
     * Auth Flyway bean. Used for the auth database. This database is persistent and should not change.
     *
     * @return Flyway bean
     */
    @Bean(name = "flywayAuth")
    @ConfigurationProperties(prefix = "flyway.auth")
    public Flyway flywayAuth() {
        Flyway flyway = Flyway.configure()
                .locations("classpath:db/migration/auth")
                .dataSource(authDataSource)
                .load();
        flyway.migrate();
        return flyway;
    }

    @Bean
    @Primary
    public FlywayMigrationInitializer flywayInitializerGame(@Qualifier("flyway") Flyway flywayGame) {
        return new FlywayMigrationInitializer(flywayGame, null);
    }

    @Bean
    public FlywayMigrationInitializer flywayInitializerProfile(@Qualifier("flywayProfile") Flyway flywayProfile) {
        return new FlywayMigrationInitializer(flywayProfile, null);
    }

    @Bean
    public FlywayMigrationInitializer flywayInitializerAuth(@Qualifier("flywayAuth") Flyway flywayAuth) {
        return new FlywayMigrationInitializer(flywayAuth, null);
    }

}

这是我的身份验证详细信息的数据源配置:

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
        entityManagerFactoryRef = "authEntityManagerFactory",
        basePackages = { "com.withergate.api.auth.repository" }
)
public class AuthDbConfig {

    /**
     * Auth datasource. Used for the auth database.
     *
     * @return datasource
     */
    @Bean(name = "authDataSource")
    @ConfigurationProperties(prefix = "auth.datasource")
    public DataSource dataSource() {
        return DataSourceBuilder.create().build();
    }

    /**
     * Auth entity manager factory. Used for the auth database.
     *
     * @return entity manager factory
     */
    @Bean(name = "authEntityManagerFactory")
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(EntityManagerFactoryBuilder builder,
            @Qualifier("authDataSource") DataSource dataSource) {
        return builder
                .dataSource(dataSource)
                .packages("com.withergate.api.auth.model")
                .persistenceUnit("auth")
                .build();
    }

    /**
     * Auth transaction manager. Used for the auth database.
     *
     * @return transaction manager
     */
    @Bean(name = "authTransactionManager")
    public PlatformTransactionManager transactionManager(
            @Qualifier("authEntityManagerFactory") EntityManagerFactory entityManagerFactory) {
        return new JpaTransactionManager(entityManagerFactory);
    }

}

当我通过 thymeleaf 登录时一切正常,但是一旦我尝试执行一些 OAuth2 请求,就会出现异常:

2020-12-11 11:55:30.668 ERROR 412122 --- [nio-8080-exec-5] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.jdbc.BadSqlGrammarException: PreparedStatementCallback; bad SQL grammar [select client_id, client_secret, resource_ids, scope, authorized_grant_types, web_server_redirect_uri, authorities, access_token_validity, refresh_token_validity, additional_information, autoapprove from oauth_client_details where client_id = ?]; nested exception is java.sql.SQLSyntaxErrorException: Table 'game.oauth_client_details' doesn't exist] with root cause

java.sql.SQLSyntaxErrorException: Table 'game.oauth_client_details' doesn't exist

似乎 OAuth2 试图使用错误的数据源来获取用户详细信息。

我的 OAuth2 配置如下所示:

@Configuration
@EnableAuthorizationServer
public class OAuth2Config extends AuthorizationServerConfigurerAdapter {

    private final UserDetailsService userService;
    private final TokenStore tokenStore;
    @Qualifier("authDataSource")
    private final DataSource dataSource;
    private final AuthenticationManager authenticationManager;

    /**
     * OAuth2Config constructor.
     */
    public OAuth2Config(
            UserDetailsService userService, TokenStore tokenStore, DataSource dataSource, @Lazy AuthenticationManager authenticationManager
    ) {
        this.userService = userService;
        this.tokenStore = tokenStore;
        this.dataSource = dataSource;
        this.authenticationManager = authenticationManager;
    }

    @Bean
    public BCryptPasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) {
        security.tokenKeyAccess("permitAll()").checkTokenAccess("isAuthenticated()");
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer configurer) {
        configurer.authenticationManager(authenticationManager);
        configurer.userDetailsService(userService);
        configurer.tokenStore(tokenStore);
    }

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.jdbc(dataSource);
    }

}

有谁知道做错了什么?

标签: javaspring-bootdatasourcespring-oauth2

解决方案


推荐阅读