练习 - 编写使用机密的 Java 应用程序

已完成

你将使用连接到数据库的 Spring Boot 来编写 Java Web 应用程序。

出于安全考虑,你需要在将来保护数据库访问。 但首先让我们创建应用程序基础结构,然后配置 Java 应用程序以供使用。

创建应用程序基础结构

在此练习中,你将使用 Azure CLI 创建以下资源:

  • 一个 Azure 资源组,其中包含应用程序的所有资源。
  • 一个 PostgreSQL 数据库服务器。
  • 一个 Azure Spring Apps 群集和一个在此群集中运行的 Spring Boot 应用程序。

需要在脚本的开头提供一些环境变量,这些变量在 Azure 中应该是唯一的。

还需要提供本地 IP 地址,以便从本地计算机访问数据库。 此 IP 地址应为 IPv4 地址。 如果你不知道本地 IP 地址,可以参阅以下网站:https://www.whatismyip.com/

设置以下环境变量:

AZ_RESOURCE_GROUP=<YOUR_UNIQUE_RESOURCE_GROUP_NAME>
AZ_DATABASE_USERNAME=<YOUR_POSTGRESQL_USERNAME>
AZ_DATABASE_PASSWORD=<YOUR_POSTGRESQL_PASSWORD>
AZ_LOCAL_IP_ADDRESS=<YOUR_LOCAL_IP_ADDRESS>

设置这些环境变量后,可以运行以下命令来创建资源:

AZ_LOCATION=eastus
# Must be all lowercase
AZ_SPRING_CLOUD=spring-${AZ_RESOURCE_GROUP,,}

AZ_DATABASE_NAME=pgsql-${AZ_RESOURCE_GROUP}
AZ_DATABASE_USERNAME=${AZ_DATABASE_USERNAME}

az group create \
    --name $AZ_RESOURCE_GROUP \
    --location $AZ_LOCATION

此命令可能需要几分钟才能完成。

az postgres server create \
    --resource-group $AZ_RESOURCE_GROUP \
    --name $AZ_DATABASE_NAME \
    --location $AZ_LOCATION \
    --sku-name B_Gen5_1 \
    --storage-size 5120 \
    --admin-user $AZ_DATABASE_USERNAME \
    --admin-password $AZ_DATABASE_PASSWORD
az postgres server firewall-rule create \
    --resource-group $AZ_RESOURCE_GROUP \
    --name $AZ_DATABASE_NAME-database-allow-local-ip \
    --server $AZ_DATABASE_NAME \
    --start-ip-address $AZ_LOCAL_IP_ADDRESS \
    --end-ip-address $AZ_LOCAL_IP_ADDRESS

az postgres server firewall-rule create \
    --resource-group $AZ_RESOURCE_GROUP \
    --name $AZ_DATABASE_NAME-database-allow-azure-ip \
    --server $AZ_DATABASE_NAME \
    --start-ip-address 0.0.0.0 \
    --end-ip-address 0.0.0.0
az postgres db create \
    --resource-group $AZ_RESOURCE_GROUP \
    --name demo \
    --server-name $AZ_DATABASE_NAME

此命令可能需要几分钟才能完成。

az extension add --name spring

az spring create \
   --name $AZ_SPRING_CLOUD \
   --resource-group $AZ_RESOURCE_GROUP \
   --location $AZ_LOCATION \
   --sku Basic

此命令可能需要几分钟才能完成。

az spring app create \
   --resource-group $AZ_RESOURCE_GROUP \
   --service $AZ_SPRING_CLOUD \
   --name application \
   --runtime-version Java_11 \
   --assign-endpoint true

这些脚本需要一段时间才能运行,因此你可以在后台运行它们,并在此期间开始编写应用程序代码。

配置 Java 应用程序

使用 git clone 命令,从 https://github.com/Azure-Samples/manage-secrets-in-java-applications GitHub 存储库获取应用程序主干:

git clone https://github.com/Azure-Samples/manage-secrets-in-java-applications.git

此应用程序使用 Spring Data JPA 访问数据库。 你可以查看 CRUD 存储库接口:

package com.example.demo;

import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface ItemRepository extends CrudRepository<Item, Integer> {
}

随后,存储在数据库中的数据会向 Web 公开(使用 Spring MVC REST 控制器):

package com.example.demo;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ItemController {

    private final ItemRepository itemRepository;

    public ItemController(ItemRepository itemRepository) {
        this.itemRepository = itemRepository;
    }

    @GetMapping("/")
    String welcome() {
        return "Here are all the database items: " + itemRepository.findAll();
    }
}

此数据会在启动时插入到数据库中(使用 src/main/resources/data.sql):

insert into item (details) values ('This is a item from the database');

如果需要更多数据或者要对文件进行自定义,可以向文件中添加更多行。

若要访问数据库,需要配置 src/main/resources/application.properties 文件:

logging.level.org.springframework.jdbc.core=DEBUG

spring.datasource.url=jdbc:postgresql://${azureDatabaseName}.postgres.database.azure.com:5432/demo
spring.datasource.username=${azureDatabaseUsername}@${azureDatabaseName}
spring.datasource.password=${azureDatabasePassword}

spring.sql.init.mode=always

此配置文件具有三个需要配置的变量:

  • ${azureDatabaseName} 是之前在 AZ_DATABASE_NAME 环境变量中配置的 PostgreSQL 数据库的名称。 键入 echo $AZ_DATABASE_NAME 可查看它。
  • ${azureDatabaseUsername} 是之前在 AZ_DATABASE_USERNAME 环境变量中配置的数据库用户名的名称。 键入 echo $AZ_DATABASE_USERNAME 可查看它。
  • ${azureDatabasePassword} 是之前在 AZ_DATABASE_PASSWORD 环境变量中配置的数据库密码的名称。 键入 echo $AZ_DATABASE_PASSWORD 可查看它。

正如我们在上一单元中了解的,在应用程序源代码中对这些值进行硬编码是一种错误的做法。 但是,若要测试应用程序,可以临时编写它们并运行应用程序:

./mvnw spring-boot:run

可以使用以下命令或 Web 浏览器通过访问 Spring MVC 控制器来读取数据库内容:

curl http://localhost:8080

将 Java 应用程序部署到 Azure

若要部署应用程序,首先需要将其打包为 Jar 文件:

./mvnw clean package

此命令在 target 目录中生成可执行 Jar 文件,你将使用 Azure CLI 部署该文件:

az spring app deploy \
   --resource-group $AZ_RESOURCE_GROUP \
   --service $AZ_SPRING_CLOUD \
   --name application \
   --artifact-path target/*.jar

如果遇到故障,可以通过键入以下命令来查看应用程序日志:

az spring app logs \
   --resource-group $AZ_RESOURCE_GROUP \
   --service $AZ_SPRING_CLOUD \
   --name application

应用程序随后将在云中可用,可以使用 cURL 命令访问其数据:

curl https://$AZ_SPRING_CLOUD-application.azuremicroservices.io

# Expected output:
#
# Here are all the database items: [Secret{Id=1, details='This is a item from the database'}]
#

祝贺你! 你已成功创建了一个连接到数据库的 Java 应用程序! 现在,需要在后续单元中保护数据库凭据。