使用 Microsoft Entra ID

适用于:SQL ServerAzure SQL 数据库Azure SQL 托管实例Azure Synapse Analytics分析平台系统(PDW)Microsoft Fabric 中的 SQL 分析终结点Microsoft Fabric 中的仓库Microsoft Fabric 中的 SQL 数据库

下载 OLE DB 驱动程序

用途

从版本 18.2.1 开始,Microsoft OLE DB Driver for SQL Server 允许 OLE DB 应用程序使用联合身份连接到 Azure SQL 数据库或 Azure SQL 托管实例、Azure Synapse Analytics 和 Microsoft Fabric。

Microsoft Entra 身份验证方法包括:

  • 用户名和密码
  • 访问令牌
  • 集成身份验证

版本 18.3.0 添加了对以下 Microsoft Entra 身份验证方法的支持:

  • 交互式身份验证

  • 托管标识身份验证(仅限在一个配置了托管标识的 Azure 虚拟机内部)

版本 18.5.0 添加了对以下身份验证方法的支持:

  • Microsoft Entra 服务主体身份验证

注意

使用以下身份验证模式,并将 DataTypeCompatibility(或其对应的属性)设置为 80 是不支持的:

  • 使用用户名和密码进行 Microsoft Entra 身份验证。
  • 使用访问令牌进行 Microsoft Entra 身份验证
  • Microsoft Entra 集成身份验证
  • Microsoft Entra 交互式身份验证
  • Microsoft Entra 托管标识身份验证
  • Microsoft Entra 服务主体身份验证

要使用 Microsoft Entra 身份验证,必须配置 Azure SQL 数据源。 有关详细信息,请参阅使用 Azure SQL 配置和管理 Microsoft Entra 身份验证

连接字符串关键字和属性

引入了以下连接字符串关键字,以支持 Microsoft Entra 身份验证:

连接字符串关键字 连接属性 说明
访问令牌 SSPROP_AUTH_ACCESS_TOKEN 指定用于在 Microsoft Entra ID 上进行身份验证的访问令牌。
身份验证 SSPROP_AUTH_MODE 指定要使用的身份验证方法。

有关新关键字/属性的详细信息,请参阅以下页面:

加密和证书验证

有关详细信息,请参阅加密和证书验证

GUI 扩展

驱动程序图形用户界面已增强,以允许 Microsoft Entra 身份验证。 有关详细信息,请参阅:

连接字符串示例

本节展示将与 IDataInitialize::GetDataSourceDBPROP_INIT_PROVIDERSTRING 属性一起使用的新连接字符串关键字和现有连接字符串关键字的示例。

SQL 身份验证

  • 使用:IDataInitialize::GetDataSource
    • 新:

      Provider=MSOLEDBSQL19;数据源=[server];初始目录=[database];Authentication=SqlPassword;用户ID=[username];密码=[password];对数据使用加密=必须

    • 已弃用:

      Provider=MSOLEDBSQL19;数据源=[server];初始 Catalog=[database];用户 ID=[username];Password=[password];对数据使用加密=必需

  • 使用:DBPROP_INIT_PROVIDERSTRING
    • 新:

      Server=[server];Database=[database];Authentication=SqlPassword;UID=[username];PWD=[password];Encrypt=Mandatory

    • 已弃用:

      Server=[server];Database=[database];UID=[username];PWD=[password];Encrypt=Mandatory

使用安全支持提供程序接口 (SSPI) 进行 Windows 集成身份验证

  • 使用:IDataInitialize::GetDataSource
    • 新:

      Provider=MSOLEDBSQL19;数据源=[server];初始目录=[database];Authentication=ActiveDirectoryIntegrated;对数据使用加密=必需

    • 已弃用:

      Provider=MSOLEDBSQL19;数据源=[server];初始 Catalog=[database];集成安全性=SSPI;对数据使用加密=必需

  • 使用:DBPROP_INIT_PROVIDERSTRING
    • 新:

      Server=[server];Database=[database];Authentication=ActiveDirectoryIntegrated;Encrypt=Mandatory

    • 已弃用:

      Server=[server];Database=[database];Trusted_Connection=yes;加密=必需

Microsoft Entra 用户名和密码身份验证

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用户帐户作为服务帐户。
  • 使用:IDataInitialize::GetDataSource

    Provider=MSOLEDBSQL19;数据源=[server];初始目录=[database];Authentication=ActiveDirectoryPassword;用户 ID=[username];密码=[password];对数据使用加密=必需

  • 使用:DBPROP_INIT_PROVIDERSTRING

    Server=[server];Database=[database];Authentication=ActiveDirectoryPassword;UID=[username];PWD=[password];Encrypt=Mandatory

Microsoft Entra 集成身份验证

  • 使用:IDataInitialize::GetDataSource

    Provider=MSOLEDBSQL19;数据源=[server];初始目录=[database];Authentication=ActiveDirectoryIntegrated;对数据使用加密=必需

  • 使用:DBPROP_INIT_PROVIDERSTRING

    Server=[server];Database=[database];Authentication=ActiveDirectoryIntegrated;Encrypt=Mandatory

使用访问令牌进行 Microsoft Entra 身份验证

  • 使用:IDataInitialize::GetDataSource

    Provider=MSOLEDBSQL19;Data Source=[server];Initial Catalog=[database];Access Token=[access token];数据加密使用=必须

  • 使用:DBPROP_INIT_PROVIDERSTRING

    不支持通过 DBPROP_INIT_PROVIDERSTRING 提供访问令牌

Microsoft Entra 交互式身份验证

  • 使用:IDataInitialize::GetDataSource

    Provider=MSOLEDBSQL19;数据源=[server];初始 Catalog=[database];Authentication=ActiveDirectoryInteractive;用户 ID=[username];对数据使用加密=必需

  • 使用:DBPROP_INIT_PROVIDERSTRING

    Server=[server];Database=[database];Authentication=ActiveDirectoryInteractive;UID=[username];Encrypt=Mandatory

Microsoft Entra 托管标识身份验证

  • 使用:IDataInitialize::GetDataSource
    • 用户分配的托管标识:

      Provider=MSOLEDBSQL19;数据源=[server];初始目录=[database];Authentication=ActiveDirectoryMSI;用户 ID=[对象 ID];数据加密必需启用

    • 系统分配的托管标识:

      Provider=MSOLEDBSQL19;数据源=[server];初始目录=[database];Authentication=ActiveDirectoryMSI;对数据使用加密=强制

  • 使用:DBPROP_INIT_PROVIDERSTRING
    • 用户分配的托管标识:

      Server=[server];Database=[database];Authentication=ActiveDirectoryMSI;UID=[对象 ID];加密=强制

    • 系统分配的托管标识:

      Server=[server];Database=[database];Authentication=ActiveDirectoryMSI;Encrypt=Mandatory

Microsoft Entra 服务主体身份验证

  • 使用:IDataInitialize::GetDataSource

    Provider=MSOLEDBSQL19;数据源=[server];初始目录=[database];Authentication=ActiveDirectoryServicePrincipal;用户ID=[应用程序(客户端)ID];密码=[Application(client)secret];对数据使用加密=必选

  • 使用:DBPROP_INIT_PROVIDERSTRING

    Server=[server];Database=[database];Authentication=ActiveDirectoryServicePrincipal;UID=[应用程序(客户端) ID];PWD=[Application (client) secret];Encrypt=Mandatory

代码示例

以下示例显示了使用连接关键字连接到 Microsoft Entra ID 所需的代码。

访问令牌

#include <string>
#include <iostream>
#include <msdasc.h>

int main()
{
    wchar_t azureServer[] = L"server";
    wchar_t azureDatabase[] = L"mydatabase";
    wchar_t accessToken[] = L"eyJ0eXAiOi...";
    IDBInitialize *pIDBInitialize = nullptr;
    IDataInitialize* pIDataInitialize = nullptr;
    HRESULT hr = S_OK;

    CoInitialize(nullptr);

    // Construct the connection string.
    std::wstring connString = L"Provider=MSOLEDBSQL19;Data Source=" + std::wstring(azureServer) + L";Initial Catalog=" + 
                              std::wstring(azureDatabase) + L";Access Token=" + accessToken + L";Use Encryption for Data=Mandatory;";
    hr = CoCreateInstance(CLSID_MSDAINITIALIZE, nullptr, CLSCTX_INPROC_SERVER, 
                          IID_IDataInitialize, reinterpret_cast<LPVOID*>(&pIDataInitialize));
    if (FAILED(hr))
    {
        std::cout << "Failed to create an IDataInitialize instance." << std::endl;
        goto Cleanup;
    }
    hr = pIDataInitialize->GetDataSource(nullptr, CLSCTX_INPROC_SERVER, connString.c_str(), 
                                         IID_IDBInitialize, reinterpret_cast<IUnknown**>(&pIDBInitialize));
    if (FAILED(hr))
    {
        std::cout << "Failed to get data source object." << std::endl;
        goto Cleanup;
    }
    hr = pIDBInitialize->Initialize();
    if (FAILED(hr))
    {
        std::cout << "Failed to establish connection." << std::endl;
        goto Cleanup;
    }

Cleanup:
    if (pIDBInitialize)
    {
        pIDBInitialize->Uninitialize();
        pIDBInitialize->Release();
    }
    if (pIDataInitialize)
    {
        pIDataInitialize->Release();
    }

    CoUninitialize();
}

Active Directory 已集成

#include <string>
#include <iostream>
#include <msdasc.h>

int main()
{
    wchar_t azureServer[] = L"server";
    wchar_t azureDatabase[] = L"mydatabase";
    IDBInitialize *pIDBInitialize = nullptr;
    IDataInitialize* pIDataInitialize = nullptr;
    HRESULT hr = S_OK;

    CoInitialize(nullptr);

    // Construct the connection string.
    std::wstring connString = L"Provider=MSOLEDBSQL19;Data Source=" + std::wstring(azureServer) + L";Initial Catalog=" + 
                              std::wstring(azureDatabase) + L";Authentication=ActiveDirectoryIntegrated;Use Encryption for Data=Mandatory;";

    hr = CoCreateInstance(CLSID_MSDAINITIALIZE, nullptr, CLSCTX_INPROC_SERVER, 
                          IID_IDataInitialize, reinterpret_cast<LPVOID*>(&pIDataInitialize));
    if (FAILED(hr)) 
    {
        std::cout << "Failed to create an IDataInitialize instance." << std::endl;
        goto Cleanup;
    }
    hr = pIDataInitialize->GetDataSource(nullptr, CLSCTX_INPROC_SERVER, connString.c_str(), 
                                         IID_IDBInitialize, reinterpret_cast<IUnknown**>(&pIDBInitialize));
    if (FAILED(hr))
    {
        std::cout << "Failed to get data source object." << std::endl;
        goto Cleanup;
    }
    hr = pIDBInitialize->Initialize();
    if (FAILED(hr))
    {
        std::cout << "Failed to establish connection." << std::endl;
        goto Cleanup;
    }

Cleanup:
    if (pIDBInitialize)
    {
        pIDBInitialize->Uninitialize();
        pIDBInitialize->Release();
    }
    if (pIDataInitialize)
    {
        pIDataInitialize->Release();
    }

    CoUninitialize();
}