使用 Microsoft Entra 身份验证进行连接

下载 JDBC 驱动程序

本文介绍了如何开发结合使用 Microsoft Entra 身份验证功能与 Microsoft JDBC Driver for SQL Server 的 Java 应用程序。

可使用 Microsoft Entra 身份验证,通过使用 Microsoft Entra ID 中的标识连接到 Azure SQL 数据库、Azure SQL 托管实例和 Azure Synapse Analytics。 Microsoft Entra 身份验证可用于集中管理数据库用户的标识,并替代 SQL Server 身份验证。 可通过 JDBC Driver 指定 JDBC 连接字符串中的 Microsoft Entra 凭据以连接到 Azure SQL。 有关如何配置 Microsoft Entra 身份验证的信息,请参阅连接使用 Microsoft Entra 身份验证访问 Azure SQL

Microsoft JDBC Driver for SQL Server 中支持 Microsoft Entra 身份验证的连接属性包括:

  • 身份验证:使用此属性以指示要用于连接的 SQL 身份验证方法。 可能的值为:
    • ActiveDirectoryManagedIdentity

      • 从驱动程序版本 8.3.1 开始,可使用 authentication=ActiveDirectoryMSI 从已启用“标识”支持的 Azure 资源连接到 Azure SQL 数据库/Synapse Analytics。 (可选)可以在 Connection/DataSource 属性中指定 msiClientId 以及此身份验证模式。 msiClientId 必须包含托管标识的客户端 ID,该 ID 将用于获取建立连接所需的 accessToken。 从驱动程序版本 v12.2 开始,还可使用 authentication=ActiveDirectoryManagedIdentity 从已启用“标识”支持的 Azure 资源连接到 Azure SQL 数据库/Synapse Analytics。 (可选)现在还可以在 user 属性中设置托管标识的客户端 ID。 有关详细信息,请参阅使用 ActiveDirectoryManagedIdentity 身份验证模式进行连接
    • ActiveDirectoryDefault

      • 从驱动程序版本 12.2 开始,可使用 authentication=ActiveDirectoryDefault 通过 Azure 标识客户端库中的 DefaultAzureCredential 连接到 Azure SQL/Synapse Analytics。 有关详细信息,请参阅使用 ActiveDirectoryDefault 身份验证进行连接
    • ActiveDirectoryIntegrated

      • 从驱动程序版本 6.0 开始,可使用 authentication=ActiveDirectoryIntegrated 通过集成身份验证连接到 Azure SQL/Synapse Analytics。 若要使用此身份验证模式,必须将本地 Active Directory 联合身份验证服务 (ADFS) 与云中的 Microsoft Entra ID联合。 设置后,连接方法有两种:一种是将本机库 mssql-jdbc_auth-<version>-<arch>.dll 添加到 Windows 上的应用程序类路径,另一种是设置用于提供跨平台身份验证支持的 Kerberos 票证。 登录已加入域的计算机后,可以访问 Azure SQL/Azure Synapse Analytics,而不会看到系统提示输入凭据。 有关详细信息,请参阅使用 ActiveDirectoryIntegrated 身份验证模式进行连接
    • ActiveDirectoryPassword

    • ActiveDirectoryInteractive

    • ActiveDirectoryServicePrincipal

      • 从驱动程序版本 9.2 开始,可使用 authentication=ActiveDirectoryServicePrincipal 通过在 userName 属性中指定应用程序/客户端 ID 和在 password 属性中指定服务主体标识的机密,连接到 Azure SQL/Synapse Analytics。 有关详细信息,请参阅使用 ActiveDirectoryServicePrincipal 身份验证模式进行连接
    • ActiveDirectoryServicePrincipalCertificate

      • 从驱动程序版本 12.4 开始,可使用 authentication=ActiveDirectoryServicePrincipalCertificate 通过在 userName 属性中指定应用程序/客户端 ID 和在 clientCertificate 属性中指定服务主体证书的位置,连接到 Azure SQL 数据库/Synapse Analytics。 有关详细信息,请参阅使用 ActiveDirectoryServicePrincipalCertificate 身份验证模式进行连接
    • SqlPassword

      • 借助 authentication=SqlPassword,可以使用 userName/user 和 password 属性连接到 SQL Server。
    • NotSpecified

      • 如果不需要这些身份验证方法,请使用 authentication=NotSpecified 或将它保留为默认值。
    • accessToken:借助此连接属性,可使用访问令牌连接到 SQL 数据库。 只能使用 DriverManager 类中 getConnection() 方法的 Properties 参数设置 accessToken。 不能在连接 URL 中使用此属性。

有关详细信息,请参阅设置连接属性页上的 authentication 属性。

客户端安装要求

除了基本驱动程序系统要求外,以下身份验证模式有更多要求。

下表列出了每种身份验证模式和驱动程序版本所需的库依赖项。 依赖项的依赖项也是必需的。

注意

如果主要版本的修补程序具有与其主要版本不同的依赖项版本,则还会列出该修补程序。

验证选项 驱动程序版本 库依赖项
ActiveDirectoryPassword
ActiveDirectoryIntegrated
6.0 Adal4j 1.3.0
ActiveDirectoryPassword
ActiveDirectoryIntegrated
6.2.2 - 6.4 Adal4j 1.4.0
ActiveDirectoryPassword
ActiveDirectoryIntegrated
7.0 Adal4j 1.6.0
ActiveDirectoryPassword
ActiveDirectoryIntegrated
7.2 Adal4j 1.6.3
Client-Runtime-for-AutoRest 1.6.5
ActiveDirectoryPassword
ActiveDirectoryIntegrated
7.4 - 8.2 Adal4jl4j 1.6.4
Client-Runtime-for-AutoRest 1.7.0
ActiveDirectoryPassword
ActiveDirectoryIntegrated
8.4 Adal4j 1.6.5
Client-Runtime-for-AutoRest 1.7.4
ActiveDirectoryPassword
ActiveDirectoryIntegrated
ActiveDirectoryInteractive
ActiveDirectoryServicePrincipal
9.2 msal4j 1.7.1
ActiveDirectoryPassword
ActiveDirectoryIntegrated
ActiveDirectoryInteractive
ActiveDirectoryServicePrincipal
9.4 msal4j 1.10.1
ActiveDirectoryPassword
ActiveDirectoryIntegrated
ActiveDirectoryInteractive
ActiveDirectoryServicePrincipal
10.2 msal4j 1.11.0
ActiveDirectoryPassword
ActiveDirectoryIntegrated
ActiveDirectoryInteractive
ActiveDirectoryServicePrincipal
11.2 msal4j 1.11.3
ActiveDirectoryPassword
ActiveDirectoryIntegrated
ActiveDirectoryInteractive
ActiveDirectoryServicePrincipal
11.2.3 msal4j 1.13.0
ActiveDirectoryPassword
ActiveDirectoryIntegrated
ActiveDirectoryInteractive
ActiveDirectoryServicePrincipal
12.2 msal4j 1.13.3
ActiveDirectoryManagedIdentity
ActiveDirectoryMSI
ActiveDirectoryDefault
12.2 azure-identity 1.7.0
ActiveDirectoryPassword
ActiveDirectoryIntegrated
ActiveDirectoryInteractive
ActiveDirectoryServicePrincipal
ActiveDirectoryServicePrincipalCertificate
12.4 msal4j 1.13.8
ActiveDirectoryManagedIdentity
ActiveDirectoryMSI
ActiveDirectoryDefault
12.4 azure-identity 1.9.0
ActiveDirectoryPassword
ActiveDirectoryIntegrated
ActiveDirectoryInteractive
ActiveDirectoryServicePrincipal
ActiveDirectoryServicePrincipalCertificate
12.6 msal4j 1.14.1
ActiveDirectoryManagedIdentity
ActiveDirectoryMSI
ActiveDirectoryDefault
12.6 azure-identity 1.11.1
ActiveDirectoryPassword
ActiveDirectoryIntegrated
ActiveDirectoryInteractive
ActiveDirectoryServicePrincipal
ActiveDirectoryServicePrincipalCertificate
12.6.3 msal4j 1.15.1
ActiveDirectoryManagedIdentity
ActiveDirectoryMSI
ActiveDirectoryDefault
12.6.3 azure-identity 1.12.2
ActiveDirectoryPassword
ActiveDirectoryIntegrated
ActiveDirectoryInteractive
ActiveDirectoryServicePrincipal
ActiveDirectoryServicePrincipalCertificate
12.6.4 msal4j 1.15.1
ActiveDirectoryManagedIdentity
ActiveDirectoryMSI
ActiveDirectoryDefault
12.6.4 azure-identity 1.12.2
ActiveDirectoryPassword
ActiveDirectoryIntegrated
ActiveDirectoryInteractive
ActiveDirectoryServicePrincipal
ActiveDirectoryServicePrincipalCertificate
12.8 msal4j 1.15.1
ActiveDirectoryManagedIdentity
ActiveDirectoryMSI
ActiveDirectoryDefault
12.8 azure-identity 1.12.2

使用 ActiveDirectoryManagedIdentity 身份验证模式进行连接

从版本 7.2 开始,支持此身份验证模式。 要使用此模式,请指定 authentication=ActiveDirectoryMSI。 从版本 12.2 开始,也可以指定 authentication=ActiveDirectoryManagedIdentity

除了客户端安装要求中列出的库依赖项要求外,此功能还具有以下要求:

下面的示例展示了如何使用 authentication=ActiveDirectoryManagedIdentity 模式。 从为托管标识配置的 Azure 资源内部运行此示例。

若要运行此示例,请将以下行中的服务器/数据库名称替换为你的服务器/数据库名称:

ds.setServerName("msentra-managed-demo.database.windows.net"); // replace 'msentra-managed-demo' with your server name
ds.setDatabaseName("demo"); // replace with your database name
//Optional
ds.setMSIClientId("<managed_identity_client>"); // Replace with Client ID of user-assigned managed identity to be used

使用 ActiveDirectoryMSI 身份验证模式的示例:

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;

import com.microsoft.sqlserver.jdbc.SQLServerDataSource;

public class MsEntraMSI {
    public static void main(String[] args) throws Exception {

        SQLServerDataSource ds = new SQLServerDataSource();
        ds.setServerName("msentra-managed-demo.database.windows.net"); // Replace with your server name
        ds.setDatabaseName("demo"); // Replace with your database name
        ds.setAuthentication("ActiveDirectoryMSI");
        // Optional
        ds.setMSIClientId("<managed_identity_client_guid>"); // Replace with Client ID of user-assigned managed identity to be used

        try (Connection connection = ds.getConnection();
                Statement stmt = connection.createStatement();
                ResultSet rs = stmt.executeQuery("SELECT SUSER_SNAME()")) {
            if (rs.next()) {
                System.out.println("You have successfully logged on as: " + rs.getString(1));
            }
        }
    }
}

下面的示例展示了如何使用 authentication=ActiveDirectoryManagedIdentity 模式。

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;

import com.microsoft.sqlserver.jdbc.SQLServerDataSource;

public class MSEntraManagedIdentity {
    public static void main(String[] args) throws Exception {

        SQLServerDataSource ds = new SQLServerDataSource();
        ds.setServerName("msentra-managed-demo.database.windows.net"); // Replace with your server name
        ds.setDatabaseName("demo"); // Replace with your database name
        ds.setAuthentication("ActiveDirectoryManagedIdentity"); // ActiveDirectoryManagedIdentity for JDBC driver version v12.2.0+
        // Optional
        ds.setUser("<managed_identity_client>"); // Replace with Client ID of User-Assigned Managed Identity to be used

        try (Connection connection = ds.getConnection();
                Statement stmt = connection.createStatement();
                ResultSet rs = stmt.executeQuery("SELECT SUSER_SNAME()")) {
            if (rs.next()) {
                System.out.println("You have successfully logged on as: " + rs.getString(1));
            }
        }
    }
}

Azure 虚拟机上的这些示例会从系统分配的托管标识或用户分配的托管标识(如果已使用托管标识的客户端 ID 指定 msiClientIduser)中提取访问令牌,并使用提取的访问令牌建立连接。 如果连接已建立,应该会看到以下消息:

You have successfully logged on as: <your Managed Identity username>

使用 ActiveDirectoryDefault 身份验证模式进行连接

ActiveDirectoryDefault 身份验证选项使用 Azure 标识客户端库的 DefaultAzureCredentialTokenCredential 实现。 凭据将链接在一起的常用身份验证方法组合在一起。

ActiveDirectoryDefault 身份验证需要在托管标识的 Azure 标识客户端库上具有运行时依赖项。 有关库版本的详细信息,请参阅客户端安装要求

下表列出了每个 JDBC 驱动程序版本的 DefaultAzureCredential 凭据链。

驱动程序版本 azure-identity 版本文档 DefaultAzureCredential
12.2 azure-identity 1.7.0 环境
托管标识
IntelliJ
Azure CLI
Azure PowerShell
12.4 azure-identity 1.9.0 环境
工作负载标识
托管标识
Azure 开发人员 CLI
IntelliJ
Azure CLI
Azure PowerShell
12.6 azure-identity 1.11.1 环境
工作负载标识
托管标识
Azure 开发人员 CLI
IntelliJ
Azure CLI
Azure PowerShell
12.8 azure-identity 1.12.2 环境
工作负载标识
托管标识
Azure 开发人员 CLI
IntelliJ
Azure CLI
Azure PowerShell

可以设置多个变量来配置 Environment 凭据。 有关配置 DefaulAzureCredential 链(包括 Environment 凭据)的详细信息,请参阅上表中链接的 azure-identity 文档的相关版本。

要在 Windows 上使用 IntellijCredential,请将环境变量 INTELLIJ_KEEPASS_PATH 设置为 keepass 文件的位置。 例如,INTELLIJ_KEEPASS_PATH=C:\user\your\path\to\the\keepass\file

要向 DefaultAzureCredential 提供更多租户,请使用 ADDITIONALLY_ALLOWED_TENANTS 环境变量。 该变量采用逗号分隔的列表。 例如: ADDITIONALLY_ALLOWED_TENANTS=<your-tenant-id-0>,<your-tenant-id-1>,<your-tenant-id-2>,...

以下示例演示如何将 authentication=ActiveDirectoryDefault 模式用于 DefaultAzureCredential 中的 AzureCliCredential

  1. 使用以下命令首次登录到 Azure CLI。

    az login
    
  2. 成功登录到 Azure CLI 后,运行以下代码。

    import java.sql.Connection;
    import java.sql.ResultSet;
    import java.sql.Statement;
    
    import com.microsoft.sqlserver.jdbc.SQLServerDataSource;
    
    public class MSEntraDefault {
        public static void main(String[] args) throws Exception {
    
            SQLServerDataSource ds = new SQLServerDataSource();
            ds.setServerName("msentra-managed-demo.database.windows.net"); // Replace with your server name
            ds.setDatabaseName("demo"); // Replace with your database name
            ds.setAuthentication("ActiveDirectoryDefault");
    
            try (Connection connection = ds.getConnection();
                    Statement stmt = connection.createStatement();
                    ResultSet rs = stmt.executeQuery("SELECT SUSER_SNAME()")) {
                if (rs.next()) {
                    System.out.println("You have successfully logged on as: " + rs.getString(1));
                }
            }
        }
    }
    

使用 ActiveDirectoryIntegrated 身份验证模式进行连接

在 Microsoft JDBC Driver for SQL Server 中,有两种使用 ActiveDirectoryIntegrated 身份验证的方法:

  • 在 Windows 上,可将来自下载的包中的 mssql-jdbc_auth-<version>-<arch>.dll 复制到系统路径中的某个位置。
  • 如果无法使用 DLL,从 6.4 版开始,可配置 Kerberos 工单。 Windows、Linux 和 macOS 等平台都支持此方法。 有关详细信息,请参阅在 Windows、Linux 和 macOS 上设置 Kerberos 票证

确保具有客户端安装要求中所需的依赖库。

下面的示例展示了如何使用 authentication=ActiveDirectoryIntegrated 模式。 此示例在与 Microsoft Entra ID 联合的域加入计算机上运行。 数据库中必须有数据库用户,此用户表示你的 Windows 用户,且必须拥有 CONNECT 权限。

执行此示例前,先将以下行中的服务器/数据库名称替换为你的服务器/数据库名称:

ds.setServerName("msentra-managed-demo.database.windows.net"); // replace 'msentra-managed-demo' with your server name
ds.setDatabaseName("demo"); // replace with your database name

使用 ActiveDirectoryIntegrated 身份验证模式的示例:

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;

import com.microsoft.sqlserver.jdbc.SQLServerDataSource;

public class MSEntraIntegrated {
    public static void main(String[] args) throws Exception {

        SQLServerDataSource ds = new SQLServerDataSource();
        ds.setServerName("msentra-managed-demo.database.windows.net"); // Replace with your server name
        ds.setDatabaseName("demo"); // Replace with your database name
        ds.setAuthentication("ActiveDirectoryIntegrated");

        try (Connection connection = ds.getConnection();
                Statement stmt = connection.createStatement();
                ResultSet rs = stmt.executeQuery("SELECT SUSER_SNAME()")) {
            if (rs.next()) {
                System.out.println("You have successfully logged on as: " + rs.getString(1));
            }
        }
    }
}

运行此示例会自动使用客户端平台的 Kerberos 票证,不需要密码。 如果连接已建立,应该会看到以下消息:

You have successfully logged on as: <your domain user name>

在 Windows、Linux 和 macOS 上设置 Kerberos 票证

必须设置 Kerberos 票证,将当前用户关联到 Windows 域帐户。 以下是关键步骤的摘要。

Windows

注意

在 Windows 上,可使用来自下载的包中的 mssql-jdbc_auth-<version>-<arch>.dll 代替这些 Kerberos 配置步骤。 仅当无法使用 DLL 时才需要这些步骤。

JDK 附带 kinit,在与 Microsoft Entra ID 联合的域加入计算机上,它可用于从密钥发行中心 (KDC) 获取 TGT。

步骤 1:票证授予票证检索
  • 运行位置:Windows

  • 操作

    • 使用命令 kinit username@DOMAIN.COMPANY.COM 从 KDC 获取 TGT,然后会看到输入域密码的提示。
    • 使用 klist 查看可用票证。 如果 kinit 成功,应会看到来自 krbtgt/DOMAIN.COMPANY.COM@ DOMAIN.COMPANY.COM 的票证。

    注意

    可能必须指定包含 -Djava.security.krb5.conf.ini 文件,以便应用程序能够找到 KDC。

Linux 和 macOS

要求

访问 Windows 域加入计算机,以查询 Kerberos 域控制器。

步骤 1:查找 Kerberos KDC
  • 运行位置:Windows 命令行

  • 操作nltest /dsgetdc:DOMAIN.COMPANY.COM(其中 DOMAIN.COMPANY.COM 映射到域名)

  • 示例输出

    DC: \\co1-red-dc-33.domain.company.com
    Address: \\2111:4444:2111:33:1111:ecff:ffff:3333
    ...
    The command completed successfully
    
  • 要提取的信息:DC 名称(在此示例中为 co1-red-dc-33.domain.company.com

步骤 2:在 krb5.conf 中配置 KDC
  • 运行位置:Linux/macOS

  • 操作:在所选编辑器中编辑 /etc/krb5.conf。 配置下列密钥

    [libdefaults]
      default_realm = DOMAIN.COMPANY.COM
    
    [realms]
    DOMAIN.COMPANY.COM = {
       kdc = co1-red-dc-28.domain.company.com
    }
    

    然后保存 krb5.conf 文件并退出

    注意

    域必须全部大写。

步骤 3:测试票证授予票证检索
  • 运行位置:Linux/macOS
  • 操作
    • 使用命令 kinit username@DOMAIN.COMPANY.COM 从 KDC 获取 TGT,然后会看到输入域密码的提示。
    • 使用 klist 查看可用票证。 如果 kinit 成功,应会看到来自 krbtgt/DOMAIN.COMPANY.COM@ DOMAIN.COMPANY.COM 的票证。

使用 ActiveDirectoryPassword 身份验证模式进行连接

下面的示例展示了如何使用 authentication=ActiveDirectoryPassword 模式。

若要生成和运行示例:

  1. 确保具有客户端安装要求中所需的依赖库。

  2. 找到以下代码行,并将服务器/数据库名称替换为你的服务器/数据库名称。

    ds.setServerName("msentra-managed-demo.database.windows.net"); // replace 'msentra-managed-demo' with your server name
    ds.setDatabaseName("demo"); // replace with your database name
    
  3. 找到以下代码行。 将用户名替换为要以其身份连接的 Microsoft Entra 用户的用户名。

    ds.setUser("bob@example.com"); // replace with your username
    ds.setPassword("password");     // replace with your password
    

使用 ActiveDirectoryPassword 身份验证模式的示例:

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;

import com.microsoft.sqlserver.jdbc.SQLServerDataSource;

public class MSEntraUserPassword {

    public static void main(String[] args) throws Exception{

        SQLServerDataSource ds = new SQLServerDataSource();
        ds.setServerName("msentra-managed-demo.database.windows.net"); // Replace with your server name
        ds.setDatabaseName("demo"); // Replace with your database
        ds.setUser("bob@example.com"); // Replace with your username
        ds.setPassword("password"); // Replace with your password
        ds.setAuthentication("ActiveDirectoryPassword");

        try (Connection connection = ds.getConnection();
                Statement stmt = connection.createStatement();
                ResultSet rs = stmt.executeQuery("SELECT SUSER_SNAME()")) {
            if (rs.next()) {
                System.out.println("You have successfully logged on as: " + rs.getString(1));
            }
        }
    }
}

如果连接已建立,应会看到输出以下消息:

You have successfully logged on as: <your user name>

使用 ActiveDirectoryInteractive 身份验证模式进行连接

下面的示例展示了如何使用 authentication=ActiveDirectoryInteractive 模式。

若要生成和运行示例:

  1. 确保具有客户端安装要求中所需的依赖库。

  2. 找到以下代码行,并将服务器/数据库名称替换为你的服务器/数据库名称。

    ds.setServerName("msentra-managed-demo.database.windows.net"); // replace 'msentra-managed-demo' with your server name
    ds.setDatabaseName("demo"); // replace with your database name
    
  3. 找到以下代码行。 将用户名替换为要以其身份连接的 Microsoft Entra 用户的用户名。

    ds.setUser("bob@example.com"); // replace with your username
    

使用 ActiveDirectoryInteractive 身份验证模式的示例:

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;

import com.microsoft.sqlserver.jdbc.SQLServerDataSource;

public class MSEntraInteractive {
    public static void main(String[] args) throws Exception{

        SQLServerDataSource ds = new SQLServerDataSource();
        ds.setServerName("msentra-managed-demo.database.windows.net"); // Replace with your server name
        ds.setDatabaseName("demo"); // Replace with your database
        ds.setAuthentication("ActiveDirectoryInteractive");

        // Optional login hint
        ds.setUser("bob@example.com"); // Replace with your user name

        try (Connection connection = ds.getConnection();
                Statement stmt = connection.createStatement();
                ResultSet rs = stmt.executeQuery("SELECT SUSER_SNAME()")) {
            if (rs.next()) {
                System.out.println("You have successfully logged on as: " + rs.getString(1));
            }
        }
    }
}

运行程序时,会显示一个浏览器来对用户进行身份验证。 看到的具体内容取决于 Microsoft Entra ID 的配置方式。 它可能包含(也可能不包括)通过手机进行用户名、密码、PIN 或第二台设备身份验证的多重身份验证提示。 在同一程序中执行了多个交互式身份验证请求时,如果身份验证库可以重复使用以前缓存的身份验证令牌,则后续请求甚至可能不会提示用户。

有关如何将 Microsoft Entra ID 配置为要求多重身份验证的信息,请参阅云中的 Microsoft Entra 多重身份验证入门

有关这些对话框的屏幕截图,请参阅使用 Microsoft Entra 多重身份验证

如果用户身份验证成功完成,则应在浏览器中看到以下消息:

Authentication complete. You can close the browser and return to the application.

此消息只表明用户身份验证成功,但不一定成功连接到了服务器。 返回到应用程序时,如果与服务器的连接已建立,应该会看到以下消息输出:

You have successfully logged on as: <your user name>

使用 ActiveDirectoryServicePrincipal 身份验证模式进行连接

下面的示例展示了如何使用 authentication=ActiveDirectoryServicePrincipal 模式。

若要生成和运行示例:

  1. 确保具有客户端安装要求中所需的依赖库。

  2. 找到以下代码行,并将服务器/数据库名称替换为你的服务器/数据库名称。

    ds.setServerName("msentra-managed-demo.database.windows.net"); // replace 'msentra-managed-demo' with your server name
    ds.setDatabaseName("demo"); // replace with your database name
    
  3. 找到以下代码行。 将 principalId 的值替换为要以其身份连接的 Microsoft Entra 服务主体的应用程序 ID/客户端 ID。 将 principalSecret 的值替换为机密。

    String principalId = "<service_principal_guid>"; // Replace with your Microsoft Entra service principal ID.
    String principalSecret = "..."; // Replace with your Microsoft Entra principal secret.
    
  4. 在版本 10.2 及更高版本中,使用 setUsersetPassword 设置主体 ID 和主体机密;在版本 9.4 及更低版本中,使用 setAADSecurePrincipalIdsetAADSecurePrincipalSecret 进行设置。

使用 ActiveDirectoryServicePrincipal 身份验证模式的示例:

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;

import com.microsoft.sqlserver.jdbc.SQLServerDataSource;

public class MSEntraServicePrincipal {
    public static void main(String[] args) throws Exception{
        String principalId = "<service_principal_guid>"; // Replace with your Microsoft Entra service principal ID.
        String principalSecret = "..."; // Replace with your Microsoft Entra principal secret.

        SQLServerDataSource ds = new SQLServerDataSource();
        ds.setServerName("msentra-managed-demo.database.windows.net"); // Replace with your server name
        ds.setDatabaseName("demo"); // Replace with your database
        ds.setAuthentication("ActiveDirectoryServicePrincipal");
        ds.setUser(principalId); // setAADSecurePrincipalId for JDBC Driver 9.4 and below
        ds.setPassword(principalSecret); // setAADSecurePrincipalSecret for JDBC Driver 9.4 and below 

        try (Connection connection = ds.getConnection();
                Statement stmt = connection.createStatement();
                ResultSet rs = stmt.executeQuery("SELECT SUSER_SNAME()")) {
            if (rs.next()) {
                System.out.println("You have successfully logged on as: " + rs.getString(1));
            }
        }
    }
}

如果连接已建立,应该会看到以下消息输出:

You have successfully logged on as: <your app/client ID>

使用 ActiveDirectoryServicePrincipalCertificate 身份验证模式进行连接

下面的示例展示了如何使用 authentication=ActiveDirectoryServicePrincipalCertificate 模式。

若要生成和运行示例:

  1. 确保具有客户端安装要求中所需的依赖库。

  2. 找到以下代码行,并将服务器/数据库名称替换为你的服务器/数据库名称。

    ds.setServerName("msentra-managed-demo.database.windows.net"); // replace 'msentra-managed-demo' with your server name
    ds.setDatabaseName("demo"); // replace with your database name
    
  3. 找到以下代码行。 将 principalId 的值替换为要以其身份连接的 Microsoft Entra 服务主体的应用程序 ID/客户端 ID。 将 clientCertificate 的值替换为服务主体证书的位置。

    String principalId = "<service_principal_guid>"; // Replace with your Microsoft Entra service principal ID.
    
    String clientCertificate = "..."; // Replace with the location for your Microsoft Entra service principal certificate.
    
  4. 如果上述证书需要密码,请使用版本 10.2 及更高版本的 setPassword 或版本 9.4 及更低版本的 setAADSecurePrincipalSecret 设置主体机密。

  5. 如果证书具有关联的私钥,请使用 setClientKey 设置私钥。 如果此密钥需要密码,请使用 setClientKeyPassword 设置私钥的密码。

使用 ActiveDirectoryServicePrincipalCertificate 身份验证模式的示例:

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;

import com.microsoft.sqlserver.jdbc.SQLServerDataSource;

public class MSEntraServicePrincipalCertificate {
    public static void main(String[] args) throws Exception{
        String principalId = "<service_principal_guid>"; // Replace with your Microsoft Entra service principal ID.
        String clientCertificate = "..."; // Replace with the location of your service principal certificate.

        SQLServerDataSource ds = new SQLServerDataSource();
        ds.setServerName("msentra-managed-demo.database.windows.net"); // Replace with your server name
        ds.setDatabaseName("demo"); // Replace with your database
        ds.setAuthentication("ActiveDirectoryServicePrincipalCertificate");
        ds.setUser(principalId); // setAADSecurePrincipalId for JDBC Driver 9.4 and below
        ds.setClientCertificate(clientCertificate);

        try (Connection connection = ds.getConnection();
             Statement stmt = connection.createStatement();
             ResultSet rs = stmt.executeQuery("SELECT SUSER_SNAME()")) {
            if (rs.next()) {
                System.out.println("You have successfully logged on as: " + rs.getString(1));
            }
        }
    }
}

如果连接已建立,应该会看到以下消息输出:

You have successfully logged on as: <your app/client ID>

使用访问令牌进行连接

应用程序/服务可以从 Microsoft Entra ID 检索访问令牌,并使用它连接到 Azure SQL 数据库、Azure SQL 托管实例及 Azure Synapse Analytics。

注意

只能使用 DriverManager 类中 getConnection() 方法的 Properties 参数设置 accessToken。 不能在连接字符串中使用此属性。 从驱动程序版本 12.2 开始,用户可以实现 accessToken 回调并将其提供给驱动程序,以便在连接池场景中续订令牌。 连接池场景要求连接池实现使用标准 JDBC 连接池类

下面的示例展示了简单的 Java 应用程序,它使用基于访问令牌的身份验证连接到 Azure。

若要生成和运行示例:

  1. 在 Microsoft Entra ID 中为服务创建应用程序帐户。

    1. 登录到 Azure 门户。
    2. 转到左侧导航栏中的 Microsoft Entra ID
    3. 选择“应用注册” 。
    4. 选择新注册
    5. 输入 mytokentest 作为应用程序的易记名称。
    6. 对于可以使用该应用程序的受支持帐户类型,请保留默认选择。
    7. 选择底部的“注册”。
    8. 不需要登录 URL。 请提供任何内容:https://mytokentest
    9. 选择底部的“Create”。
    10. 选择“注册”后,应用将立即创建完成,并进入其资源页面。
    11. 在“Essentials”框中,找到“应用程序(客户端)ID”并复制。 稍后需要用到此值来配置应用程序。
    12. 从导航面板选择“证书和机密”。 在“客户端密码 (0)”选项卡上,选择“新建客户端密码”。 输入密码的说明,选择过期时间(保留默认即可)。 选择底部的“添加”。 重要注意事项:离开此页面之前,请务必复制生成的客户端密码“值”, 离开此页面后无法查看此值。 此值为客户端密码。
    13. 返回到 Microsoft Entra ID 的应用注册窗格,并找到“端点”选项卡。复制 OAuth 2.0 token endpoint 下面的 URL, 这是 STS URL。

    Azure 门户应用注册终结点 - STS URL

  2. 以 Microsoft Entra 管理员身份连接至数据库,并使用 T-SQL 命令为应用程序主体预配包含的数据库用户。 有关如何创建 Microsoft Entra 管理员和包含的数据库用户的详细信息,请参阅使用 Microsoft Entra 身份验证连接

    CREATE USER [mytokentest] FROM EXTERNAL PROVIDER
    
  3. 在运行此示例的客户端计算机上下载 Microsoft Authentication Library (MSAL) for Java 库及其依赖项。 MSAL仅用于运行此特定示例。 此示例使用这个库中的 API 从 Microsoft Entra ID 检索访问令牌。 如果已有访问令牌,则可以跳过此步骤,并删除示例中检索访问令牌的部分。

在下面的示例中,将 STS URL、客户端 ID、客户端密码、服务器和数据库名称替换为你的值。

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import com.microsoft.sqlserver.jdbc.SQLServerDataSource;

// The microsoft-authentication-library-for-java is needed to retrieve the access token in this example.
import com.microsoft.aad.msal4j.ClientCredentialFactory;
import com.microsoft.aad.msal4j.ClientCredentialParameters;
import com.microsoft.aad.msal4j.ConfidentialClientApplication;
import com.microsoft.aad.msal4j.IAuthenticationResult;
import com.microsoft.aad.msal4j.IClientCredential;

public class MSEntraTokenBased {

    public static void main(String[] args) throws Exception {

        // Retrieve the access token from Microsoft Entra ID.
        String spn = "https://database.windows.net/";
        String stsurl = "https://login.microsoftonline.com/..."; // Replace with your STS URL.
        String clientId = "<service_principal_guid>"; // Replace with your client ID.
        String clientSecret = "..."; // Replace with your client secret.

        String scope = spn +  "/.default";
        Set<String> scopes = new HashSet<>();
        scopes.add(scope);

        ExecutorService executorService = Executors.newSingleThreadExecutor();
        IClientCredential credential = ClientCredentialFactory.createFromSecret(clientSecret);
        ConfidentialClientApplication clientApplication = ConfidentialClientApplication
            .builder(clientId, credential).executorService(executorService).authority(stsurl).build();
        CompletableFuture<IAuthenticationResult> future = clientApplication
            .acquireToken(ClientCredentialParameters.builder(scopes).build());

        IAuthenticationResult authenticationResult = future.get();
        String accessToken = authenticationResult.accessToken();

        System.out.println("Access Token: " + accessToken);

        // Connect with the access token.
        SQLServerDataSource ds = new SQLServerDataSource();

        ds.setServerName("msentra-managed-demo.database.windows.net"); // Replace with your server name.
        ds.setDatabaseName("demo"); // Replace with your database name.
        ds.setAccessToken(accessToken);

        try (Connection connection = ds.getConnection();
                Statement stmt = connection.createStatement();
                ResultSet rs = stmt.executeQuery("SELECT SUSER_SNAME()")) {
            if (rs.next()) {
                System.out.println("You have successfully logged on as: " + rs.getString(1));
            }
        }
    }
}

如果连接成功,应该会看到以下消息输出:

Access Token: <your access token>
You have successfully logged on as: <your client ID>

使用访问令牌回调进行连接

与访问令牌属性一样,访问令牌回调允许注册为驱动程序提供访问令牌的方法。 对属性进行回调的好处在于回调允许驱动程序在令牌过期时请求新的访问令牌。 例如,创建新连接的连接池可以请求具有全新有效期的新令牌。 有关详细信息,请参阅使用连接池

以下示例演示如何实现和设置 accessToken 回调。

import com.microsoft.aad.msal4j.IClientCredential;
import com.microsoft.aad.msal4j.ClientCredentialFactory;
import com.microsoft.aad.msal4j.ConfidentialClientApplication;
import com.microsoft.aad.msal4j.IAuthenticationResult;
import com.microsoft.aad.msal4j.ClientCredentialParameters;
import java.sql.Connection;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class MSEntraAccessTokenCallback {

    public static void main(String[] args) {

        SQLServerAccessTokenCallback callback = new SQLServerAccessTokenCallback() {
            @Override
            public SqlAuthenticationToken getAccessToken(String spn, String stsurl) {

                String clientSecret = "..."; // Replace with your client secret.
                String clientId = "<service_principal_guid>"; // Replace with your client ID.

                String scope = spn + "/.default";
                Set<String> scopes = new HashSet<>();
                scopes.add(scope);

                try {
                    ExecutorService executorService = Executors.newSingleThreadExecutor();
                    IClientCredential credential = ClientCredentialFactory.createFromSecret(clientSecret);
                    ConfidentialClientApplication clientApplication = ConfidentialClientApplication
                            .builder(clientId, credential).executorService(executorService).authority(stsurl).build();
                    CompletableFuture<IAuthenticationResult> future = clientApplication
                            .acquireToken(ClientCredentialParameters.builder(scopes).build());

                    IAuthenticationResult authenticationResult = future.get();
                    String accessToken = authenticationResult.accessToken();

                    return new SqlAuthenticationToken(accessToken, authenticationResult.expiresOnDate().getTime());
                } catch (Exception e) {
                    e.printStackTrace();
                }
                return null;
            }
        };

        SQLServerDataSource ds = new SQLServerDataSource();
        ds.setServerName("msentra-managed-demo.database.windows.net"); // Replaces with your server name.
        ds.setDatabaseName("demo"); // Replace with your database name.
        ds.setAccessTokenCallback(callback);

        try (Connection connection = ds.getConnection();
                Statement stmt = connection.createStatement();
                ResultSet rs = stmt.executeQuery("SELECT SUSER_SNAME()")) {
            if (rs.next()) {
                System.out.println("You have successfully logged on as: " + rs.getString(1));
            }
        }
    }
}

如果连接成功,应该会看到以下消息输出:

You have successfully logged on as: <your client ID>

从版本 12.4 开始,可以通过 accessToken 连接字符串属性设置 accessTokenCallbackClass 回调。 下面的示例演示了如何使用此属性设置 accessToken 回调:

import com.microsoft.aad.msal4j.IClientCredential;
import com.microsoft.aad.msal4j.ClientCredentialFactory;
import com.microsoft.aad.msal4j.ConfidentialClientApplication;
import com.microsoft.aad.msal4j.IAuthenticationResult;
import com.microsoft.aad.msal4j.ClientCredentialParameters;
import java.sql.Connection;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

 

public class MSEntraAccessTokenCallbackClass {
    public static class AccessTokenCallbackClass implements SQLServerAccessTokenCallback {
        @Override
        public SqlAuthenticationToken getAccessToken(String spn, String stsurl) {
            String clientSecret = "..."; // Replace with your client secret.
            String clientId = "<service_principal_guid>"; // Replace with your client ID.
            
            String scope = spn + "/.default";
            Set<String> scopes = new HashSet<>();
            scopes.add(scope);
            
            try {
                ExecutorService executorService = Executors.newSingleThreadExecutor();
                IClientCredential credential = ClientCredentialFactory.createFromSecret(clientSecret);
                ConfidentialClientApplication clientApplication = ConfidentialClientApplication

                        .builder(clientId, credential).executorService(executorService).authority(stsurl).build();
                
                CompletableFuture<IAuthenticationResult> future = clientApplication
                        .acquireToken(ClientCredentialParameters.builder(scopes).build());
                
                IAuthenticationResult authenticationResult = future.get();
                String accessToken = authenticationResult.accessToken();
                
                return new SqlAuthenticationToken(accessToken, authenticationResult.expiresOnDate().getTime());
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
    }
    
    public static void main(String[] args) throws Exception {
        
        SQLServerDataSource ds = new SQLServerDataSource();
        ds.setServerName("msentra-managed-demo.database.windows.net"); // Replaces with your server name.
        ds.setDatabaseName("demo"); // Replace with your database name.
        ds.setAccessTokenCallbackClass(AccessTokenCallbackClass.class.getName());
        
        try (Connection connection = ds.getConnection();
             Statement stmt = connection.createStatement();
             ResultSet rs = stmt.executeQuery("SELECT SUSER_SNAME()")) {
            if (rs.next()) {
                System.out.println("You have successfully logged on as: " + rs.getString(1));
            }
        }
    }
}

如果连接成功,应该会看到以下消息输出:

You have successfully logged on as: <your client ID>

后续步骤

通过以下文章详细了解相关概念: