你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

教程:从 Azure 应用服务 上的 Java JBoss EAP 连接到 MySQL 数据库

在本教程中,您将学习如何使用托管标识将 Azure 应用服务 上的 Java JBoss EAP 应用程序连接到 Azure Database for MySQL。 应用服务可以使用 托管标识提供对 Azure Database for MySQL 和其他Azure服务的安全访问。 使用托管身份可以避免在应用中使用机密信息,比如运行环境变量中的凭证。

本教程使用Azure CLI命令来完成以下任务:

  • 创建 Azure Database for MySQL 服务器和数据库。
  • 使用 WAR 包将示例 JBoss EAP 应用部署到应用服务。
  • 将 Spring Boot Web 应用程序配置为对 MySQL 数据库使用Microsoft Entra身份验证。
  • 使用具有托管标识身份验证的服务连接器将 Web 应用连接到 MySQL 数据库。

先决条件

  • 在支持服务连接器的Azure区域中,拥有Microsoft Entra角色分配权限和Azure资源写入权限的Azure订阅,并且为教程提供足够的应用服务支持和配额。

  • 在 Azure 订阅中注册的 Microsoft.ServiceLinkerMicrosoft.DBforMySQL 资源提供程序。 可以运行 az provider register -n Microsoft.[service] 来注册提供程序。

  • Git 访问和克隆示例存储库。

  • 访问 Azure Cloud Shell 以运行教程步骤,或者如果想要在本地运行,则满足以下先决条件和步骤:

    • Java JDK 安装

    • 已安装 Maven

    • jq 安装

    • 已安装 MySQL 客户端

    • 已安装 Azure CLI 2.46.0 或更高版本。 若要检查版本,请运行 az --version。 若要升级,请运行 az upgrade

      如果你在本地运行的话:

      1. 使用 az login 并按照提示登录Azure。
      2. 如果有多个 Azure 订阅连接到登录凭据,请运行 az account set --subscription <subscription-ID> 以选择正确的订阅。

配置您的环境

  1. 安装以下 Azure CLI 扩展:

    az extension add --name serviceconnector-passwordless --upgrade
    az extension add --name rdbms-connect
    
  2. 运行以下命令,将示例存储库克隆,并将目录更改为示例应用项目文件夹。 运行此文件夹中的所有剩余命令。

    git clone https://github.com/Azure-Samples/Passwordless-Connections-for-Java-Apps
    cd Passwordless-Connections-for-Java-Apps/JakartaEE/jboss-eap/
    
  3. 为本教程定义以下环境变量,将 <region> 占位符替换为有效值。 LOCATION必须是一个 Azure 区域,其中您的订阅有足够的配额来创建 Azure 资源,并且不会对任何服务有限制。

    LOCATION="<region>"
    RESOURCE_GROUP="mysql-mi-webapp"
    
  4. 创建Azure资源组以包含所有项目资源。 资源组名称会进行缓存并自动应用于后续命令。

    az group create --name $RESOURCE_GROUP --location $LOCATION
    

创建 Azure Database for MySQL(Azure MySQL 数据库)

在订阅中创建一个 Azure Database for MySQL 服务器和数据库。 Spring Boot 应用连接到此数据库并在运行时存储其数据,无论在何处运行应用程序,应用程序状态都保持不变。

  1. 运行以下命令以创建Azure Database for MySQL服务器。 MYSQL_HOST名称在所有Azure中必须是唯一的。

    注意

    尽管该命令定义了管理员帐户,但不会使用该帐户,因为Microsoft Entra管理员帐户执行所有管理任务。

    export MYSQL_ADMIN_USER=azureuser
    export MYSQL_ADMIN_PASSWORD="AdminPassword1"
    export RAND_ID=$RANDOM
    export MYSQL_HOST="mysql-mi-$RAND_ID"
    az mysql flexible-server create \
        --name $MYSQL_HOST \
        --resource-group $RESOURCE_GROUP \
        --location $LOCATION \
        --admin-user $MYSQL_ADMIN_USER \
        --admin-password $MYSQL_ADMIN_PASSWORD \
        --public-access 0.0.0.0 \
        --tier Burstable \
        --sku-name Standard_B1ms \
        --storage-size 32
    
  2. 创建一个名为供应用程序使用的数据库 checklist

    export DATABASE_NAME="checklist"
    az mysql flexible-server db create \
        --resource-group $RESOURCE_GROUP \
        --server-name $MYSQL_HOST \
        --database-name $DATABASE_NAME
    
  3. 打开防火墙以允许从当前 IP 地址连接到数据库。

    # Create a temporary firewall rule to allow connections from your current machine to the MySQL server
    export MY_IP=$(curl http://whatismyip.akamai.com)
    az mysql flexible-server firewall-rule create \
        --resource-group $RESOURCE_GROUP \
        --name $MYSQL_HOST \
        --rule-name AllowCurrentMachineToConnect \
        --start-ip-address ${MY_IP} \
        --end-ip-address ${MY_IP}
    
  4. 连接到数据库并创建 /azure/init-db.sql 示例项目文件中指定的表。

    export DATABASE_FQDN=${MYSQL_HOST}.mysql.database.azure.com
    export CURRENT_USER=$(az account show --query user.name --output tsv)
    export RDBMS_ACCESS_TOKEN=$(az account get-access-token \
        --resource-type oss-rdbms \
        --output tsv \
        --query accessToken)
    mysql -h "${DATABASE_FQDN}" --user "${CURRENT_USER}" --password="$RDBMS_ACCESS_TOKEN" < azure/init-db.sql
    
  5. 移除临时的防火墙规则。

    az mysql flexible-server firewall-rule delete \
        --resource-group $RESOURCE_GROUP \
        --name $MYSQL_HOST \
        --rule-name AllowCurrentMachineToConnect
    

创建应用服务资源

在 Linux 上创建应用服务 JBoss EAP 资源。 JBoss EAP 需要高级 sku 层。

# Create an App Service plan
export APPSERVICE_PLAN="mysql-mi-plan"
export APPSERVICE_NAME="mysql-mi-app"
az appservice plan create \
    --resource-group $RESOURCE_GROUP \
    --name $APPSERVICE_PLAN \
    --location $LOCATION \
    --sku P1V3 \
    --is-linux

# Create an App Service web app
az webapp create \
    --resource-group $RESOURCE_GROUP \
    --name $APPSERVICE_NAME \
    --plan $APPSERVICE_PLAN \
    --runtime "JBOSSEAP:7-java8"

创建并配置用户分配的托管标识

使用以下命令创建Azure用户分配的托管标识以用于Microsoft Entra身份验证。 有关详细信息,请参阅设置 Azure Database for MySQL 灵活服务器的 Microsoft Entra 身份验证

export USER_IDENTITY_NAME="my-user-assigned-identity"
export IDENTITY_RESOURCE_ID=$(az identity create \
    --name $USER_IDENTITY_NAME \
    --resource-group $RESOURCE_GROUP \
    --query id \
    --output tsv)

授予新用户分配身份 User.Read.AllGroupMember.Read.AllApplication.Read.All 权限。 或者,为身份提供 Directory Readers Microsoft Entra 内置角色。

不支持使用Azure CLI分配Microsoft Entra权限或角色。 可以使用 Microsoft Entra 管理中心、Microsoft Graph PowerShell 或 Microsoft Graph API 来创建分配。 有关详细信息,请参阅分配 Microsoft Entra 角色

注意

若要添加这些分配,必须在 Microsoft Entra 租户中至少具有 Privileged Role Administrator 角色或权限。 如果没有此角色,请要求 全局管理员特权角色管理员 授予权限。

使用托管标识连接服务

使用 服务连接器 将应用服务 JBoss EAP Web 应用连接到具有托管标识的 MySQL 数据库。 服务连接器在后台执行以下任务:

  • 将当前登录用户设置为Microsoft Entra数据库管理员。
  • 为应用启用系统分配的托管标识。
  • 为系统分配的托管标识添加数据库用户,并向此用户授予所有数据库权限。
  • 将名为 AZURE_MYSQL_CONNECTIONSTRING 的连接字符串添加到应用的 App Settings

使用以下 az webapp connection create 命令,使用托管标识将应用连接到 MySQL 数据库。

az webapp connection create mysql-flexible \
    --resource-group $RESOURCE_GROUP \
    --name $APPSERVICE_NAME \
    --target-resource-group $RESOURCE_GROUP \
    --server $MYSQL_HOST \
    --database $DATABASE_NAME \
    --system-identity mysql-identity-id=$IDENTITY_RESOURCE_ID \
    --client-type java

生成和部署应用

  1. 运行以下代码,将无密码身份验证插件添加到生成的 连接字符串 服务连接器。 应用启动脚本引用此连接字符串。

    export PASSWORDLESS_URL=$(\
        az webapp config appsettings list \
            --resource-group $RESOURCE_GROUP \
            --name $APPSERVICE_NAME \
        | jq -c '.[] \
        | select ( .name == "AZURE_MYSQL_CONNECTIONSTRING" ) \
        | .value' \
        | sed 's/"//g')
    # Create a new environment variable with the connection string including the passwordless authentication plugin
    export PASSWORDLESS_URL=${PASSWORDLESS_URL}'&defaultAuthenticationPlugin=com.azure.identity.extensions.jdbc.mysql.AzureMysqlAuthenticationPlugin&authenticationPlugins=com.azure.identity.extensions.jdbc.mysql.AzureMysqlAuthenticationPlugin'
    az webapp config appsettings set \
        --resource-group $RESOURCE_GROUP \
        --name $APPSERVICE_NAME \
        --settings "AZURE_MYSQL_CONNECTIONSTRING_PASSWORDLESS=${PASSWORDLESS_URL}"
    
  2. 使用示例应用中的 pom.xml 文件来构建应用并生成 WAR 文件。

    mvn clean package -DskipTests
    
  3. 将 WAR 文件和启动脚本部署到应用服务。

    az webapp deploy \
        --resource-group $RESOURCE_GROUP \
        --name $APPSERVICE_NAME \
        --src-path target/ROOT.war \
        --type war
    az webapp deploy \
        --resource-group $RESOURCE_GROUP \
        --name $APPSERVICE_NAME \
        --src-path src/main/webapp/WEB-INF/createMySQLDataSource.sh \
        --type startup
    

测试应用程序

  1. 运行以下代码以创建包含某些列表项的列表。

    export WEBAPP_URL=$(az webapp show \
        --resource-group $RESOURCE_GROUP \
        --name $APPSERVICE_NAME \
        --query defaultHostName \
        --output tsv)/$DATABASE_NAME
    
    # Create a list
    curl -X POST -H "Content-Type: application/json" -d '{"name": "list1","date": "2022-03-21T00:00:00","description": "Sample checklist"}' https://${WEBAPP_URL}
    
    # Create few items on the list 1
    curl -X POST -H "Content-Type: application/json" -d '{"description": "item 1"}' https://${WEBAPP_URL}/1/item
    curl -X POST -H "Content-Type: application/json" -d '{"description": "item 2"}' https://${WEBAPP_URL}/1/item
    curl -X POST -H "Content-Type: application/json" -d '{"description": "item 3"}' https://${WEBAPP_URL}/1/item
    
  2. 如果在本地工作,请运行以下代码以查看应用:

    # Get all list items
    curl https://${WEBAPP_URL}
    
    # Get list item 1
    curl https://${WEBAPP_URL}/1
    

    Cloud Shell无法打开本地浏览器,因此,如果使用的是 Cloud Shell,查看 Web 应用的最简单方法是选择应用Azure门户页面顶部附近的 BrowseDefault 域链接。 然后,在浏览器中追加 /checklist/checklist/1 附加到 URL 的末尾,例如 https://mysql-mi-app.azurewebsites.net/checklist

清理资源

完成本教程后,可以通过删除所创建的资源来避免产生进一步的费用。 删除资源组以删除它包含的所有资源。 在运行命令之前,请确保不再需要资源。

az group delete --name $RESOURCE_GROUP --no-wait

删除所有资源可能需要一些时间。 该 --no-wait 参数允许命令立即返回。