首页 > 解决方案 > 如何使用 Spring Data JPA 访问 Azure AD 集成 Postgres DB?

问题描述

我们有一个在 Azure 中运行的 PostgreSQL 单一服务实例,它集成了 Azure AD。所以要通过psql我按照以下步骤进行连接:

  1. 通过登录az login
  2. 检索访问令牌$env:PGPASSWORD=$(az account get-access-token --resource-type oss-rdbms --query accessToken --output tsv)
  3. 登录psql "host=single-server-instance.postgres.database.azure.com user=aad_group@single-server-instance dbname=demodb"

到目前为止,一切都很好。但是我将如何使用 Spring Data JPA 做到这一点?

这就是我当前application.properties文件的样子。当然,我不想一遍又一遍地插入访问令牌。

logging.level.org.hibernate.SQL=DEBUG

spring.datasource.url=jdbc:postgresql://single-server-instance.postgres.database.azure.com:5432/demodb
spring.datasource.username=aad_group@single-server-instance
spring.datasource.password=eyJ...there goes the access token

spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect    
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=create-drop

这是我的依赖项build.gradle

// ...
dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    implementation 'org.springframework.boot:spring-boot-starter-web'
    runtimeOnly 'org.postgresql:postgresql'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
// ...

问题:

  1. 我应该将配置部分移动到我的代码中spring.datasource并从那里spring.jpa提供访问令牌吗?spring.datasource.password如果是这样,我该怎么做?它应该去哪里?
  2. 如何检索访问令牌并将其传递给 Spring Data?
  3. 我应该如何处理访问令牌的缓存?我是否必须处理刷新令牌并处理访问令牌到期?

标签: javaspringspring-data-jpapostgresql-11azure-postgresql

解决方案


我们扩展了HikairDataSource并覆盖了它的getPassword()方法,该方法在创建新连接之前调用。

import com.azure.core.credential.AccessToken;
import com.azure.core.credential.SimpleTokenCache;
import com.azure.core.credential.TokenCredential;
import com.azure.core.credential.TokenRequestContext;
import com.zaxxer.hikari.HikariDataSource;

@Component
@ConfigurationProperties(prefix = "spring.datasource.hikari")
public class AzureAdDataSource extends HikariDataSource {

    private final SimpleTokenCache cache;

    public AzureAdDataSource(TokenCredential aadTokenCredential) {
        this.cache = new SimpleTokenCache(() -> aadTokenCredential.getToken(createRequestContext()));
    }

    @Override
    public String getPassword() {
        final AccessToken accessToken = cache.getToken()
                                             .retry(1L)
                                             .blockOptional()
                                             .orElseThrow(() -> new RuntimeException("Attempt to retrieve AAD token failed"));
        return accessToken.getToken();
    }

    private static TokenRequestContext createRequestContext() {
        return new TokenRequestContext().addScopes("https://ossrdbms-aad.database.windows.net/.default");
    }
}

使用的库:'com.azure:azure-identity:1.3.3', 'com.zaxxer:HikariCP:4.0.3'

调整属性,或者在配置文件中创建 AzureAdDataSource 的实例,而不是将其注释为组件:

spring.datasource.hikari.jdbc-url=jdbc:postgresql://single-server-instance.postgres.database.azure.com:5432/demodb
spring.datasource.hikari.username=aad_group@single-server-instance

推荐阅读