Azure Synapse Scala:使用MSI访问令牌无法获取Azure SQL Server数据
问题描述
已通过系统分配身份为SQL数据库配置链接服务,在Azure Synapse的Scala笔记本中执行指定代码时,触发登录失败错误:
com.microsoft.sqlserver.jdbc.SQLServerException: Login failed for user ''. ClientConnectionId:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/
使用用户名+密码方式可正常获取数据,需排查遗漏的配置步骤。
相关代码:
import com.microsoft.azure.synapse.tokenlibrary.TokenLibrary import java.util.Properties val jdbcHostname = ".sql.azuresynapse.net" val jdbcPort = 1433 val jdbcDatabase = "" // Create the JDBC URL without passing in the user and password parameters. val jdbcUrl = s"jdbc:sqlserver://${jdbcHostname}:${jdbcPort};database=${jdbcDatabase}" // Create a Properties() object to hold the parameters. val connectionProperties = new Properties() // Driver that can also be observed in the log when using the 'native' Synapse SQL way. val driverClass = "com.microsoft.sqlserver.jdbc.SQLServerDriver" connectionProperties.setProperty("Driver", driverClass) // Create a linked server to your dedicated pool with a Manged Identity connectionProperties.setProperty("accessToken", mssparkutils.credentials.getConnectionStringOrCreds("samplesqllink")) // Define your query val pushdown_query = "(select top 10 ID from dbo.tblEmployees) data_alias" val df = spark.read.jdbc(url=jdbcUrl, table=pushdown_query, properties=connectionProperties) display(df)
排查与解决步骤
补全系统分配身份的数据库权限
- 进入目标SQL数据库的**访问控制(IAM)**页面,为Synapse工作区的系统分配托管身份添加
SQL DB Contributor角色(或具备数据读取权限的自定义角色)。 - 若目标是Synapse专用SQL池,需在池内执行以下SQL,为托管身份创建数据库用户并授权:
CREATE USER [你的Synapse工作区名称] FROM EXTERNAL PROVIDER; ALTER ROLE db_datareader ADD MEMBER [你的Synapse工作区名称];
- 进入目标SQL数据库的**访问控制(IAM)**页面,为Synapse工作区的系统分配托管身份添加
修正链接服务与代码配置的一致性
- 检查链接服务
samplesqllink,确认身份验证方式为系统分配托管身份。 - 补全代码中
jdbcHostname和jdbcDatabase的有效值,确保与链接服务配置的目标服务器、数据库完全一致。
- 检查链接服务
调整访问令牌获取逻辑
替换令牌获取代码为针对SQL资源的专用令牌请求:connectionProperties.setProperty("accessToken", TokenLibrary.getAccessToken("https://database.windows.net/"))(原代码使用
getConnectionStringOrCreds可能返回非令牌格式内容,需确认链接服务配置是否匹配该方法的返回预期)完善JDBC URL参数
添加加密连接参数,符合Azure SQL的安全要求:val jdbcUrl = s"jdbc:sqlserver://${jdbcHostname}:${jdbcPort};database=${jdbcDatabase};encrypt=true"
内容的提问来源于stack exchange,提问作者Ajith Kumar
相关产品推荐
相关产品推荐

