使用 go-mssqldb 进行 Microsoft Entra ID 身份验证

go-mssqldb 驱动程序支持通过 azuread 软件包进行 Microsoft Entra ID 身份验证。 该包注册了一个名为 azuresql 的独立驱动程序,它对标准 sqlserver 驱动程序进行封装,并提供 Microsoft Entra ID 凭证支持。

注意

所有内置的 fedauth 身份验证方法都需要名为 azuresql 的驱动程序(而非 sqlserver)。 如果将 sql.Open("sqlserver", ...)fedauth 参数一起使用,身份验证会以 Login failed for user '' 的形式静默失败。 导入 azuread 包,并如以下示例所示使用 azuresql

选择 FedAuth 流程

请使用下表为您的托管环境和凭据来源选择合适的流程:

如果你需要从……进行连接... 从...开始 在以下情况下使用...
地方发展 ActiveDirectoryDefault 你想在不配置本地服务主体或托管身份的情况下,重用 Azure CLI 或 Azure Developer CLI 凭证。
一个由Azure托管的应用,带有管理身份 ActiveDirectoryManagedIdentity 你希望生产配置可预测,不希望链中有其他本地凭证源。
Azure DevOps 中的 CI/CD 管道 ActiveDirectoryAzurePipelines 你的管道已使用 Azure 服务连接,并公开了 SYSTEM_ACCESSTOKEN
Kubernetes 中的 Azure 工作负载标识 ActiveDirectoryWorkloadIdentity 你的 Pod 会收到一个 OIDC 令牌文件,你需要的是工作负载身份而不是客户端秘密。
一个带有秘密或证书的服务主体 ActiveDirectoryServicePrincipal 你的应用作为应用注册进行认证,你管理客户端秘密或证书。
一个已经有访问令牌的工具 ActiveDirectoryServicePrincipalAccessToken自定义令牌提供程序 你的应用会在驱动程序之外获取并刷新代币。
来自上游 Web API 的委托用户令牌 ActiveDirectoryOnBehalfOf 你需要在中间层服务中将用户令牌交换为 SQL 作用域令牌。
开发者工具或交互工具 ActiveDirectoryInteractiveActiveDirectoryDeviceCodeActiveDirectoryAzCliActiveDirectoryAzureDeveloperCli 有人在场可进行登录,或者你想复用现有的本地 CLI 会话。
一个仅支持Windows的应用,处理集成认证要求 ActiveDirectoryIntegrated (高级) 你为集成场景提供了自定义的代币获取逻辑。

如果你在本地开发和 Azure 托管环境中共用一个连接字符串,ActiveDirectoryDefault 是一个很好的起点。 用于生产环境,使用 ActiveDirectoryManagedIdentityActiveDirectoryServicePrincipal 避免凭证链延迟。

安装azuread包

下载 azureadazuresql 包,用于注册驱动程序:

go get github.com/microsoft/go-mssqldb/azuread

使用 AzureSQL 驱动

导入 azuread 包(代替或附加基础 go-mssqldb 包),并使用 azuresql 驱动名打开连接:

import (
    "database/sql"

    _ "github.com/microsoft/go-mssqldb/azuread"
)

func main() {
    db, err := sql.Open("azuresql",
        "sqlserver://<server>.database.windows.net?database=AdventureWorks2025&fedauth=ActiveDirectoryDefault&encrypt=true&TrustServerCertificate=false")
    // ...
}

以下所有示例均针对Azure SQL。 在连接字符串中保留 encrypt=true&TrustServerCertificate=false,以便驱动程序验证服务器证书。

Fedauth 凭证类型

fedauth 连接参数设置为以下值之一。 大多数类型都对应于来自 azidentity 包的 Azure Identity 凭据。 ActiveDirectoryServicePrincipalAccessToken 自定义令牌提供者API使用调用者提供的令牌。

ActiveDirectoryDefault

使用 azidentity.DefaultAzureCredential,它会按顺序尝试以下凭据来源:

  1. 环境变量(AZURE_TENANT_ID、, AZURE_CLIENT_ID等等)。
  2. 适用于 Kubernetes 的工作负载身份
  3. 托管身份。
  4. Azure CLI 凭据
  5. Azure 开发人员 CLI 凭据
sqlserver://<server>.database.windows.net?database=AdventureWorks2025&fedauth=ActiveDirectoryDefault&encrypt=true&TrustServerCertificate=false

本地开发时使用这种类型,因为它会自动获取 Azure CLI 凭证。 在生产环境中,请直接使用 ActiveDirectoryManagedIdentityActiveDirectoryServicePrincipalDefaultAzureCredential 在第一次连接时逐一逐一访问凭证源,这增加了生产工作负载不需要的延迟。

ActiveDirectoryManagedIdentity

使用系统分配的或用户分配的托管身份进行身份验证。 对于用户分配的标识,请在 user id 参数中提供客户端 ID:

sqlserver://<server>.database.windows.net?database=AdventureWorks2025&fedauth=ActiveDirectoryManagedIdentity&encrypt=true&TrustServerCertificate=false

使用用户分配的身份:

sqlserver://<server>.database.windows.net?database=AdventureWorks2025&fedauth=ActiveDirectoryManagedIdentity&user id=<client-id>&encrypt=true&TrustServerCertificate=false

注释

ActiveDirectoryMSIActiveDirectoryManagedIdentity 的别名。

ActiveDirectoryServicePrincipal

使用客户端 ID 和客户端密码,以服务主体(应用注册)身份进行身份验证:

sqlserver://<server>.database.windows.net?database=AdventureWorks2025&fedauth=ActiveDirectoryServicePrincipal&user id=<client-id>&password=<client-secret>&encrypt=true&TrustServerCertificate=false

对于基于证书的服务主体认证,使用 clientcertpath=<path-to-certificate>password=<certificate-password>一起使用。

注释

ActiveDirectoryApplicationActiveDirectoryServicePrincipal 的别名。

ActiveDirectoryServicePrincipalAccessToken

使用预先获取的服务主体访问令牌,你的应用程序直接在连接字符串中传递该令牌:

sqlserver://<server>.database.windows.net?database=AdventureWorks2025&fedauth=ActiveDirectoryServicePrincipalAccessToken&password=<access-token>&encrypt=true&TrustServerCertificate=false

只有当你的应用已经在驱动程序外部获取并刷新了访问令牌时,才使用这个流程。 对于大多数服务对服务场景,优先使用 ActiveDirectoryServicePrincipal 或自定义令牌提供者。

Active Directory 密码

Important

Microsoft SQL 驱动程序中弃用 ActiveDirectoryPassword 身份验证选项(Microsoft Entra ID密码身份验证)。 此高风险身份验证流与强制Microsoft Entra多重身份验证(MFA)不兼容,在强制实施 MFA 的租户中可能不起作用。 计划迁移到其他Microsoft Entra身份验证方法。

Microsoft Entra ID密码身份验证基于 OAuth 2.0 资源所有者密码凭据(ROPC)授予,允许应用程序直接处理其密码来登录用户。

Microsoft建议不要使用 ROPC 流,因为它与 MFA 不兼容。 在大多数情况下,可以使用我们建议的更安全的替代方案。 此流要求在应用程序中高度信任,并且存在在其他流中不存在的风险。 仅当更安全的流不可行时,才使用此流。 Microsoft正远离此高风险身份验证流,以保护用户免受恶意攻击。 有关详细信息,请参阅 规划 Azure 的强制多重身份验证

如果登录时有用户在场,请使用 ActiveDirectoryInteractive 或 ActiveDirectoryIntegrated 身份验证,以便审核跟踪记录归属于已登录用户,并使条件访问策略生效。

对于无人值守的服务到服务场景,请遵循Microsoft Entra 服务帐户指南

  • 如果应用程序在Azure基础结构上运行,请使用 ActiveDirectoryMSI(或某些驱动程序中的 ActiveDirectoryManagedIdentity)。 托管标识消除了维护和轮换机密和证书的开销。
  • 如果托管标识不可用(例如,应用程序在 Azure 外部运行),请使用 ActiveDirectoryServicePrincipal。 在驱动程序支持的情况下,应优先使用客户端证书,而非客户端机密。 使用证书时,私钥会保留在客户端上,并且仅将签名断言发送到Microsoft Entra对客户端进行身份验证。 如果密钥存储在硬件(如 TPM 或 HSM)中,或者被标记为不可导出,就无法像客户端密码那样以字符串形式将其复制出来。
  • 不要使用Microsoft Entra用户帐户作为服务帐户。

使用Microsoft Entra用户名和密码进行身份验证:

sqlserver://<server>.database.windows.net?database=AdventureWorks2025&fedauth=ActiveDirectoryPassword&user id=<user>@mydomain.com&password=<password>&applicationclientid=<app-id>&encrypt=true&TrustServerCertificate=false

applicationclientid 参数是该流的必要条件。

ActiveDirectoryInteractive

为用户打开基于浏览器的交互式登录提示。 适用于本地开发工具:

sqlserver://<server>.database.windows.net?database=AdventureWorks2025&fedauth=ActiveDirectoryInteractive&user id=<user>@mydomain.com&applicationclientid=<app-id>&encrypt=true&TrustServerCertificate=false

applicationclientid 参数是该流的必要条件。

ActiveDirectoryDeviceCode

显示一个设备代码,供用户在 https://microsoft.com/devicelogin 输入。 适用于无浏览器环境:

sqlserver://<server>.database.windows.net?database=AdventureWorks2025&fedauth=ActiveDirectoryDeviceCode&encrypt=true&TrustServerCertificate=false

ActiveDirectoryAzCli

使用已登录的 Azure CLI 会话中的令牌:

sqlserver://<server>.database.windows.net?database=AdventureWorks2025&fedauth=ActiveDirectoryAzCli&encrypt=true&TrustServerCertificate=false

ActiveDirectoryAzureDeveloperCli

使用已登录的 Azure Developer CLI(azd)会话中的令牌:

sqlserver://<server>.database.windows.net?database=AdventureWorks2025&fedauth=ActiveDirectoryAzureDeveloperCli&encrypt=true&TrustServerCertificate=false

ActiveDirectory环境

从环境变量读取凭证。 Azure 标识库会检查以下变量,例如 AZURE_TENANT_IDAZURE_CLIENT_IDAZURE_CLIENT_SECRET

sqlserver://<server>.database.windows.net?database=AdventureWorks2025&fedauth=ActiveDirectoryEnvironment&encrypt=true&TrustServerCertificate=false

Active Directory 工作负载标识

通过工作负载身份联合进行身份验证。 在配置 Azure 工作负载身份的 Kubernetes pods 中使用此方法。

sqlserver://<server>.database.windows.net?database=AdventureWorks2025&fedauth=ActiveDirectoryWorkloadIdentity&encrypt=true&TrustServerCertificate=false

Active Directory Azure Pipelines

通过使用 Azure Pipelines 服务连接进行认证。 可以在 连接字符串 中提供管道参数,或者让驱动程序读取 Azure Pipelines 环境变量的缺失值。

sqlserver://<server>.database.windows.net?database=AdventureWorks2025&fedauth=ActiveDirectoryAzurePipelines&user id=<client-id>@<tenant-id>&serviceconnectionid=<service-connection-id>&systemtoken=<system-access-token>&encrypt=true&TrustServerCertificate=false

根据驱动程序的要求设置参数:

参数 Description
user id 服务主体客户端 ID,后面可选择跟上 @tenant-id
serviceconnectionid 来自 Azure DevOps 的服务连接 ID。
systemtoken 管道系统访问令牌()。$(System.AccessToken)

ActiveDirectoryClientAssertion

使用客户端断言(已签名的 JWT 令牌)而非客户端密钥进行身份验证。 在参数 clientassertion 中提供带符号的JWT:

sqlserver://<server>.database.windows.net?database=AdventureWorks2025&fedauth=ActiveDirectoryClientAssertion&user id=<client-id>@<tenant-id>&clientassertion=<jwt-token>&encrypt=true&TrustServerCertificate=false

ActiveDirectoryOnBehalfOf

通过 On-Behalf-Of (OBO) 流进行身份验证。 驱动程序将上游用户令牌交换为一个作用范围为 SQL Server 的新令牌。

sqlserver://<server>.database.windows.net?database=AdventureWorks2025&fedauth=ActiveDirectoryOnBehalfOf&user id=<client-id>@<tenant-id>&password=<client-secret>&userassertion=<user-token>&encrypt=true&TrustServerCertificate=false

客户端身份验证阶段可以使用 passwordclientcertpathclientassertion,但始终需要 userassertion

Active Directory 集成

支持高级集成身份验证工作流。 该模式需要通过令牌提供者进行自定义的令牌获取逻辑。

此模式仅在Windows上使用。 在 Linux 和 macOS 上,使用自定义令牌提供者来进行认证流程。

sqlserver://<server>.database.windows.net?database=AdventureWorks2025&fedauth=ActiveDirectoryIntegrated&encrypt=true&TrustServerCertificate=false

自定义令牌提供者

如果内置 fedauth 类型都不适合你的场景,可以使用以下令牌提供者API之一来提供你自己的令牌获取逻辑:

当你拥有预先获得的OAuth2访问令牌时,可以使用这个API:

import (
    "context"
    "database/sql"
    "log"

    "github.com/microsoft/go-mssqldb"
)

connector, err := mssql.NewSecurityTokenConnector(
    "sqlserver://<server>.database.windows.net?database=AdventureWorks2025&encrypt=true&TrustServerCertificate=false",
    func(ctx context.Context) (string, error) {
        // Return a pre-acquired OAuth2 access token.
        return myTokenProvider(ctx)
    },
)
if err != nil {
    log.Fatal(err)
}
db := sql.OpenDB(connector)

NewAccessTokenConnector (简化API)

使用该 API 实现更简单的令牌获取,无需上下文处理。

import (
    "database/sql"
    "log"

    "github.com/microsoft/go-mssqldb"
)

connector, err := mssql.NewAccessTokenConnector(
    "sqlserver://<server>.database.windows.net?database=AdventureWorks2025&encrypt=true&TrustServerCertificate=false",
    func() (string, error) {
        // Return a pre-acquired OAuth2 access token.
        return mySimpleTokenProvider()
    },
)
if err != nil {
    log.Fatal(err)
}
db := sql.OpenDB(connector)

NewActiveDirectoryTokenConnector(自定义 ADAL 工作流)

当内置的 fedauth 模式和 SecurityToken API 均不适用于你的场景时,请使用此 API 进行自定义 Azure AD 令牌获取工作流:

import (
    "context"
    "database/sql"
    "log"

    "github.com/microsoft/go-mssqldb"
)

connector, err := mssql.NewActiveDirectoryTokenConnector(
    "sqlserver://<server>.database.windows.net?database=AdventureWorks2025&encrypt=true&TrustServerCertificate=false",
    mssql.FedAuthADALWorkflowPassword,
    func(ctx context.Context, serverSPN, stsURL string) (string, error) {
        // Custom ADAL workflow using server-provided SPN and STS URL.
        return myCustomADALFlow(ctx, serverSPN, stsURL)
    },
)
if err != nil {
    log.Fatal(err)
}
db := sql.OpenDB(connector)

当你需要与自定义身份提供者集成、实现令牌缓存,或处理包未覆盖 azuread 的凭证类型时,这种方法非常有用。 大多数应用应使用 NewSecurityTokenConnector 预购代币。

常见的资格选项

以下参数适用于多种联邦认证类型:

参数 Description
applicationclientid 客户端应用ID。 这是 ActiveDirectoryPasswordActiveDirectoryInteractive 所必需的。
clientcertpath 用于基于证书的服务主体身份验证或代表用户(On-Behalf-Of)身份验证的 PEM 或 PFX 客户端证书文件的路径。
clientassertion 用于 ActiveDirectoryClientAssertion 或 On-Behalf-Of 身份验证的已签名 JWT 断言。
serviceconnectionid Azure Pipelines 服务连接 ID
systemtoken Azure Pipelines 的系统访问令牌
userassertion 用于 ActiveDirectoryOnBehalfOf 的上游用户令牌。
tokenfilepath Kubernetes 中 ActiveDirectoryWorkloadIdentity 的 OIDC 令牌文件路径。
additionallyallowedtenants 在需要多租户身份验证时允许的额外租户 ID 的逗号分隔列表。
disableinstancediscovery 设置为 true 以禁用实例发现;仅在你控制权威 URL 时使用。
sendcertificatechain 设置为 true 发送基于证书的认证链。