容器应用通过用户分配托管身份连接SQL数据库时MSI令牌获取失败
用户分配托管身份连接Azure SQL数据库失败:MSI Token获取失败
报错信息
ERROR 1 --- [main] com.zaxxer.hikari.pool.HikariPool: HikariPool-1 - Exception during pool initialization. com.microsoft.sqlserver.jdbc.SQLServerException: MSI Token failure: Failed to acquire token from MSI Endpoint at com.microsoft.sqlserver.jdbc.SQLServerSecurityUtility.getMSIAuthToken(SQLServerSecurityUtility.java:499) ~[mssql-jdbc-11.2.3.jre17.jar:na] ...
应用配置
pom.xml
... <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.1.1</version> <relativePath /> </parent> <properties> <java.version>17</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>com.microsoft.sqlserver</groupId> <artifactId>mssql-jdbc</artifactId> </dependency> <dependency> <groupId>com.azure</groupId> <artifactId>azure-identity</artifactId> <version>1.5.4</version> </dependency> </dependencies> ...
application.properties
spring.datasource.driverClassName=com.microsoft.sqlserver.jdbc.SQLServerDriver spring.jpa.hibernate.dialect=org.hibernate.dialect.SQLServerDialect spring.datasource.url=jdbc:sqlserver://danieltestsqlserver1101.database.windows.net:1433;databaseName=testdatabase01;msiClientId=<managed-identity-client-id>;authentication=ActiveDirectoryMSI;
Azure配置步骤
- 创建用户分配托管身份“mi-test-app”
- 创建AD组“DB admin”,将“mi-test-app”和主用户添加为成员与所有者
- 创建SQL Server,将“DB admin”组设置为服务器管理员
- 为SQL Server创建专用终结点并禁用公网访问
- 创建专用DNS区域并配置虚拟网络链接
- 在SQL数据库中执行以下脚本:
CREATE USER [mi-test-app] FROM EXTERNAL PROVIDER; ALTER ROLE db_datareader ADD MEMBER [mi-test-app]; ALTER ROLE db_datawriter ADD MEMBER [mi-test-app]; ALTER ROLE db_ddladmin ADD MEMBER [mi-test-app]; GO - 创建带独立环境的容器应用,添加“mi-test-app”到身份列表并重启修订版本
排查与解决步骤
1. 验证容器应用的托管身份关联
- 确认容器应用的身份配置中,用户分配托管身份“mi-test-app”已被正确添加,且状态为“已启用”
- 检查容器应用的环境变量是否设置了
AZURE_CLIENT_ID,值为托管身份的Client ID(azure-identity库需要此变量明确指定用户分配身份)
2. 修正JDBC认证配置与依赖版本
- Spring Boot 3.x搭配mssql-jdbc 11.x时,推荐使用
ActiveDirectoryDefault认证模式替代ActiveDirectoryMSI,该模式会自动通过azure-identity库获取令牌 - 更新azure-identity到最新稳定版本(如1.12.0),旧版本在容器环境中可能存在令牌获取兼容性问题
- 修改JDBC URL为:
spring.datasource.url=jdbc:sqlserver://danieltestsqlserver1101.database.windows.net:1433;databaseName=testdatabase01;authentication=ActiveDirectoryDefault; - 确保容器应用环境变量中添加
AZURE_CLIENT_ID=<managed-identity-client-id>
3. 确认SQL Server与托管身份的权限同步
- 登录SQL Server,执行
SELECT name, type_desc FROM sys.server_principals WHERE name = 'mi-test-app',确认托管身份已存在于服务器主体中 - 若未找到,需重新同步AD组权限:可先移除“DB admin”组的服务器管理员权限,等待5分钟后重新添加,再验证服务器主体是否出现
4. 排查网络连通性
- 确认容器应用所在虚拟网络与SQL Server专用终结点所在虚拟网络已连通(对等连接或同一VNet)
- 检查专用DNS区域的A记录是否正确指向SQL Server专用终结点的IP,且容器应用能解析该域名
- 验证容器应用能否访问Azure实例元数据服务(IMDS):在容器内执行
curl http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://database.windows.net/,若无法访问则需检查容器环境的网络策略
5. 启用调试日志定位问题
- 在application.properties中添加日志配置:
logging.level.com.azure.identity=DEBUG logging.level.com.microsoft.sqlserver.jdbc=DEBUG - 查看容器应用的详细日志,获取令牌请求的具体错误原因(如权限不足、身份未找到、网络超时等)
内容的提问来源于stack exchange,提问作者dgolive
相关产品推荐
相关产品推荐

