迁移 Java 应用程序以将无密码连接用于 Azure SQL 数据库

本文介绍如何从传统身份验证方法迁移到更安全且无密码的连接与Azure SQL 数据库。

应用程序对 Azure SQL 数据库发出的请求必须经过身份验证。 Azure SQL 数据库为应用提供多种不同的安全连接方式。 其中一种方法是使用密码。 但是,应尽可能确定应用程序中无密码连接的优先级。

比较身份验证选项

当应用程序使用 Azure SQL 数据库 进行身份验证时,它提供用于连接到数据库的用户名和密码对。 根据标识的存储位置,有两种类型的身份验证:Microsoft Entra 身份验证和Azure SQL 数据库身份验证。

Microsoft Entra 身份验证

Microsoft Entra 身份验证是一种使用 Microsoft Entra ID 中定义的标识连接到Azure SQL 数据库的机制。 使用 Microsoft Entra 身份验证,可以在中心位置管理数据库用户标识和其他Microsoft 服务,从而简化权限管理。

使用 Microsoft Entra ID 进行身份验证具有以下优势:

  • 以统一的方式在 Azure 服务中对用户进行身份验证。
  • 在单个位置管理密码策略和密码轮换。
  • Microsoft Entra ID 支持的多种形式的身份验证,因此无需存储密码。
  • 客户可以使用外部(Microsoft Entra ID)组管理数据库权限。
  • Microsoft Entra 身份验证使用 Azure SQL 数据库用户对数据库级别的标识进行身份验证。
  • 支持连接到 Azure SQL 数据库 的应用程序基于令牌的身份验证。

Azure SQL 数据库身份验证

可以在Azure SQL 数据库中创建帐户。 如果你选择使用密码作为帐户的凭据,这些凭据将存储在 sys.database_principals 表中。 由于这些密码存储在Azure SQL 数据库中,因此需要自行管理密码的轮换。

尽管可以使用密码连接到Azure SQL 数据库,但应谨慎使用它们。 必须勤奋地不要在不安全的位置公开密码。 获得密码访问权限的任何人都可以进行身份验证。 例如,如果意外连接字符串被检查到源代码管理中、通过不安全的电子邮件发送、粘贴到错误的聊天中或由不应拥有权限的人员查看,恶意用户可能会访问应用程序。 请考虑改为将应用程序更新为使用无密码连接。

引入无密码连接

使用无密码连接,无需在应用程序代码、配置文件或环境变量中存储任何凭据即可连接到 Azure 服务。

许多 Azure 服务支持无密码连接,例如通过 Azure 托管标识。 这些技术提供可靠的安全功能,可以使用 Azure 标识客户端库中的 DefaultAzureCredential 实现。 本教程介绍如何更新现有应用程序以使用DefaultAzureCredential,而不是连接字符串等替代方法。

DefaultAzureCredential 支持多种身份验证方法,并自动确定应在运行时使用哪种方法。 应用通过此方法能够在不同环境(本地开发与生产)中使用不同的身份验证方法,而无需实现特定于环境的代码。

可在 Azure 标识库概述中找到搜索凭据的顺序和位置DefaultAzureCredential。 例如,在本地工作时, DefaultAzureCredential 通常会使用开发人员用于登录 Visual Studio 的帐户进行身份验证。 将应用部署到 Azure 后,DefaultAzureCredential 将自动切换为使用托管标识。 此转换不需要进行任何代码更改。

若要确保连接无密码,必须同时考虑本地开发和生产环境。 如果任一位置都需要连接字符串,则应用程序不是无密码的。

在本地开发环境中,可以使用适用于 Visual Studio Code 或 IntelliJ 的 Azure CLI、Azure PowerShell、Visual Studio 或 Azure 插件进行身份验证。 在这种情况下,可以在应用程序中使用该凭据,而不是配置属性。

将应用程序部署到 Azure 托管环境(例如虚拟机)时,可以在该环境中分配托管标识。 然后,无需提供凭据即可连接到 Azure 服务。

注意

托管标识提供用于表示应用或服务的安全标识。 标识由 Azure 平台托管,无需设置或转交任何机密。 可以在概述文档中详细了解托管标识。

注意

由于用于Azure SQL 数据库的 JDBC 驱动程序尚不支持来自本地环境的无密码连接,本文将只关注部署到 Azure 托管环境的应用程序,以及如何将其迁移到使用无密码连接。

迁移现有应用程序以使用无密码连接

以下步骤说明如何迁移现有应用程序以使用无密码连接,而不是基于密码的解决方案。

0) 准备工作环境

首先,使用以下命令设置一些环境变量。

export AZ_RESOURCE_GROUP=<YOUR_RESOURCE_GROUP>
export AZ_DATABASE_SERVER_NAME=<YOUR_DATABASE_SERVER_NAME>
export AZ_DATABASE_NAME=demo
export CURRENT_USERNAME=$(az ad signed-in-user show --query userPrincipalName --output tsv)
export CURRENT_USER_OBJECTID=$(az ad signed-in-user show --query id --output tsv)

使用以下值替换占位符,在本文中将使用这些值:

  • <YOUR_RESOURCE_GROUP>:资源位于的资源组的名称。
  • <YOUR_DATABASE_SERVER_NAME>:Azure SQL 数据库服务器的名称。 它在 Azure 中应是唯一的。

1) 配置Azure SQL 数据库

1.1) 启用基于 Microsoft Entra ID 的身份验证

若要将 Microsoft Entra ID 访问与Azure SQL 数据库配合使用,应首先设置 Microsoft Entra 管理员用户。 只有 Microsoft Entra 管理员用户可以为基于 Microsoft Entra ID 的身份验证创建/启用用户。

如果使用 Azure CLI,请运行以下命令以确保该用户拥有足够的权限:

az login --scope https://graph.microsoft.com/.default

然后运行以下命令来设置 Microsoft Entra 管理员:

az sql server ad-admin create \
    --resource-group $AZ_RESOURCE_GROUP \
    --server $AZ_DATABASE_SERVER_NAME \
    --display-name $CURRENT_USERNAME \
    --object-id $CURRENT_USER_OBJECTID

此命令会将 Microsoft Entra 管理员设置为当前已登录用户。

注意

每个Azure SQL 数据库服务器只能创建一个 Microsoft Entra 管理员。 选择另一个将覆盖为服务器配置的现有 Microsoft Entra 管理员。

2) 迁移应用代码以使用无密码连接

接下来,使用以下步骤更新代码以使用无密码连接。 虽然从概念上讲相似,但每种语言使用不同的实现详细信息。

  1. 在项目中,添加对包的以下引用 azure-identity 。 此库包含实现无密码连接所需的所有实体。

    <dependency>
         <groupId>com.azure</groupId>
         <artifactId>azure-identity</artifactId>
         <version>1.5.4</version>
    </dependency>
    
  2. 在 JDBC URL.v 中启用 Microsoft Entra 托管标识身份验证,识别当前创建java.sql.Connection连接到Azure SQL 数据库的代码中的位置。 更新代码,使之与以下示例一致:

    String url = "jdbc:sqlserver://$AZ_DATABASE_SERVER_NAME.database.windows.net:1433;databaseName=$AZ_DATABASE_NAME;authentication=ActiveDirectoryMSI;"   
    Connection con = DriverManager.getConnection(url);
    
  3. 将两 $AZ_DATABASE_SERVER_NAME 个变量和一个 $AZ_DATABASE_NAME 变量替换为本文开头配置的值。

  4. user删除 JDBC URL 以及password从 JDBC URL 中删除。

3) 配置 Azure 托管环境

将应用程序配置为使用无密码连接后,相同的代码可以在部署到 Azure 后向 Azure 服务进行身份验证。 例如,部署到已分配托管标识的Azure App 服务实例的应用程序可以连接到Azure 存储。

在本部分中,你将执行两个步骤,使应用程序能够以无密码方式在 Azure 托管环境中运行:

  • 为 Azure 托管环境分配托管标识。
  • 将角色分配给托管标识。

注意

Azure 还提供服务连接器,可帮助将托管服务与 SQL Server 连接。 使用服务连接or 来配置托管环境,可以省略将角色分配给托管标识的步骤,因为服务连接或会为你执行此操作。 以下部分介绍如何通过两种方式配置 Azure 托管环境:一种是通过服务连接或另一种方式直接配置每个托管环境。

重要

服务连接程序命令需要 Azure CLI 2.41.0 或更高版本。

使用Azure 门户分配托管标识

以下步骤演示如何为各种 Web 托管服务分配系统分配的托管标识。 托管标识可以使用之前设置的应用配置安全地连接到其他 Azure 服务。

  1. 在Azure App 服务实例的主概述页上,从导航窗格中选择“标识”。

  2. “系统分配 ”选项卡上,确保将 “状态 ”字段设置为 “打开”。 系统分配的标识由 Azure 在内部进行管理,并为你处理管理任务。 标识的详细信息和 ID 永远不会在代码中公开。

    Screenshot of Azure portal Identity page of App Service resource with System assigned tab showing and Status field highlighted.

还可以使用 Azure CLI 在 Azure 托管环境中分配托管标识。

可以使用 az webapp identity assign 命令将托管标识分配给Azure App 服务实例,如以下示例所示:

export AZ_MI_OBJECT_ID=$(az webapp identity assign \
    --resource-group $AZ_RESOURCE_GROUP \
    --name <service-instance-name> \
    --query principalId \
    --output tsv)

为托管标识分配角色

接下来,向创建的托管标识授予访问 SQL 数据库的权限。

如果使用 Service 连接or 连接了服务,则上一步的命令已分配了角色,因此可以跳过此步骤。

测试应用程序

进行这些代码更改后,可以生成并重新部署应用程序。 然后,在浏览器中浏览到托管的应用程序。 应用应能够成功连接到 Azure SQL 数据库。 请记住,角色分配通过 Azure 环境传播最长可能需要五分钟的时间。 应用程序现在配置为在本地和生产环境中运行,开发人员无需管理应用程序本身的机密。

后续步骤

本教程介绍了如何将应用程序迁移到无密码连接。

可以阅读以下资源,更深入地了解本文中讨论的概念: