You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何不重启服务刷新HikariDataSource连接SQL Server的过期AccessToken

解决方案

根因说明

你在初始化HikariDataSource Bean时一次性获取访问令牌写入静态配置,后续所有新连接创建都会复用该令牌,Azure AD令牌默认有效期仅1小时,过期后没有自动更新机制,就会触发登录失败报错。

实现步骤

1. 版本依赖确认

确保使用的com.microsoft.sqlserver:mssql-jdbc版本≥10.2.0,该版本开始支持accessTokenCallback配置,可在每次新建连接时动态获取令牌。同时com.microsoft.azure:msal4j保持最新稳定版本即可。

2. 复用MSAL令牌缓存

将MSAL的ConfidentialClientApplication实例注册为单例Bean,MSAL内置令牌缓存会自动处理令牌刷新,无需每次请求Azure AD接口,只有令牌快过期时才会自动调用接口拉取新令牌。

@Bean
public ConfidentialClientApplication confidentialClientApplication(
        @Value("${azure.ad.client-id}") String clientId,
        @Value("${azure.ad.client-secret}") String clientSecret,
        @Value("${azure.ad.tenant-id}") String tenantId
) throws MalformedURLException {
    return ConfidentialClientApplication.builder(clientId, ClientCredentialFactory.createFromSecret(clientSecret))
            .authority("https://login.microsoftonline.com/" + tenantId)
            .build();
}

3. 封装令牌获取回调

封装令牌获取逻辑,每次调用时优先从MSAL缓存中取有效令牌:

@Autowired
private ConfidentialClientApplication clientApplication;

@Value("${azure.ad.sql.scope}") // 格式通常为 https://database.windows.net/.default
private String sqlScope;

private Supplier<String> accessTokenSupplier() {
    return () -> {
        Set<String> scopes = Collections.singleton(sqlScope);
        ClientCredentialParameters parameters = ClientCredentialParameters.builder(scopes).build();
        try {
            IAuthenticationResult result = clientApplication.acquireToken(parameters).join();
            return result.accessToken();
        } catch (Exception e) {
            throw new RuntimeException("获取Azure AD访问令牌失败", e);
        }
    };
}

4. 修改Hikari数据源配置

删除原有静态写入accessToken的逻辑,改为配置accessTokenCallback,同时设置连接最大生命周期小于令牌有效期,避免连接池中存在使用过期令牌的存活连接:

@Bean
public DataSource dataSource() {
    HikariConfig config = new HikariConfig();
    // 基础配置保持不变:JDBC地址、连接池大小、超时时间等
    config.setJdbcUrl("你的SQL Server JDBC连接串");
    config.setPoolName("SqlserverCP");
    config.setConnectionTimeout(30000);

    // 核心配置1:配置令牌回调,每次新建连接时动态获取最新有效令牌
    config.getDataSourceProperties().put("accessTokenCallback", accessTokenSupplier());

    // 核心配置2:连接最大生命周期设为55分钟,短于Azure AD令牌默认1小时有效期
    config.setMaxLifetime(3300000);

    // 可选配置:借出连接前校验有效性,进一步避免无效连接返回给业务
    config.setTestOnBorrow(true);
    config.setConnectionTestQuery("SELECT 1");

    return new HikariDataSource(config);
}

原理说明

修改后每次JDBC驱动创建新连接时,都会自动调用配置的令牌回调获取最新的有效令牌完成认证,配合Hikari的连接生命周期管理,旧连接会在令牌过期前被自动销毁,全程无需重启服务,也不需要手动处理令牌刷新逻辑。


内容的提问来源于stack exchange,提问作者KikeSP

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 05:24:01