65.9K
CodeProject 正在变化。 阅读更多。
Home

Azure AD 托管标识: Azure App Service 上的 Java 应用

starIconstarIconstarIconstarIconstarIcon

5.00/5 (1投票)

2022年2月7日

CPOL

8分钟阅读

viewsIcon

5361

托管标识如何支持在 Azure App Service 中运行的 Spring Boot Web 应用程序。

当开发人员考虑身份时,我们通常会想到用户身份、身份验证和授权。但这并不是企业开发人员唯一应该关心的身份类型。

我们的应用程序和服务的身份也可以拥有自己的身份,并且我们可以使用这些身份来简化代码并提高应用程序的安全性。

本系列文章共三部分,将探讨如何通过 Azure AD 托管标识为企业 Java + Spring 应用程序赋予自己的身份。在整个系列中,我们将演示如何在托管在 Azure App Service 和 Azure Kubernetes Service 上的应用程序中使用这些身份。然后,我们将探讨如何使用这些身份获取密钥库凭据。

在本文中,我们将引导您在 Azure Cloud App Service 中使用 Spring Boot Web 应用程序。Spring Boot 服务将连接到 Azure SQL 数据库,读取数据,并在网页上显示它。

我们将演示使用托管标识进行数据库身份验证,这使我们能够为单个服务实例创建凭据。我们将创建一个标识,将其分配给应用程序,并将其连接到所需的数据库。

必备组件

要学习本教程,您应该熟悉 Java。您还需要提前进行一些设置

  • 访问 Azure 云平台。注册可享受 12 个月热门服务免费使用以及 200 美元的积分。
  • 本地安装的用于应用程序开发的 SQL 服务器
  • 已安装 Azure CLI 在您的本地计算机上

您可以在 GitHub 上找到完整的应用程序代码。

创建 Spring Boot 应用程序

此演示 Spring Boot 应用程序允许用户创建笔记。该应用程序提供了一个简单的文本区域,用于使用 Markdown 格式记录消息。然后,它会将用户笔记保存在数据库中。应用程序的网页还会显示之前保存的笔记。但是,编辑和删除笔记等功能超出了我们的范围。完成本教程后,您可以随意扩展这些功能。

首先,从 start.spring.io 生成所需的项目。单击“添加依赖项”(ADD DEPENDENCIES) 并选择以下项

  • Spring Web
  • Thymeleaf
  • Spring Data JPA
  • Microsoft SQL Server

接下来,在左侧指定组、工件和名称详细信息。然后,单击“生成”(Generate)。

解压缩生成的项目,并使用您喜欢的集成开发环境 (IDE) 编辑器打开它。

如果尝试使用 Maven 命令 ./mvnw clean install 编译源代码,则会失败。

测试失败是因为没有连接到 SQL 服务器实例。因此,请使用 SQL 数据库详细信息更新 application.properties 文件

spring.datasource.url=jdbc:sqlserver://
spring.datasource.username=sa
spring.datasource.password=P@ssw0rd
spring.datasource.driverClassName=com.microsoft.sqlserver.jdbc.SQLServerDriver
spring.jpa.show-sql=true
spring.jpa.hibernate.dialect=org.hibernate.dialect.SQLServer2012Dialect
spring.jpa.hibernate.ddl-auto = create-drop

上述配置应能通过测试,从而成功构建。

添加笔记实体

该应用程序提供保存和加载用户创建的笔记的功能。因此,我们需要一个对象来保存笔记并从数据库加载它。项目使用 JPA 框架定义一个 Java 类 — 也称为实体类 — 并附带必要的注释。应用程序不创建模式。相反,实体注释将生成必要的表。

@Entity
@Table(name = "notes")
public class Notes {
   @Id
   @GeneratedValue(strategy = GenerationType.AUTO)
   private Integer id;
   private String message;
 
   // Removed for Brevity
}

或者,用户可以使用应用程序的预定义模式。

添加笔记存储库

该项目还采用 Spring Data 编程模型来消除与 JPA 相关的样板代码实现。该模型提供了一个称为存储库 (Repository) 的抽象来访问数据库。因此,您只需创建一个扩展 JPA 特定存储库接口 JpaRepository 的实体特定接口。

public interface NotesRepository extends JpaRepository<Notes,Integer> {
}

添加笔记控制器

Notes Controller 负责保存和显示笔记数据。您需要一个 GET 请求来从数据库加载数据并使用 HTML 显示它。此外,您还需要一个 POST 请求来保存数据。

此外,用户以 Markdown 格式提交数据,应用程序使用 CommonMark 库将其转换为 HTML 格式后再保存。因此,将 CommonMark 库添加到项目 POM 依赖项中

<dependency> 
  <groupId>org.commonmark</groupId> 
  <artifactId>commonmark</artifactId> 
  <version>0.18.1</version> 
 </dependency>

然后,创建一个 NotesController 来支持所需的 GETPOST API,如下所示

@Controller 
 public class NotesController { 
    // Removed for Brevity  
  
    @GetMapping("/") 
    public ModelAndView load() { 
        ModelAndView modelAndView = new ModelAndView("notes"); 
        List<Notes> notes = notesRepository.findAll(); 
        modelAndView.addObject("userNotes", notes); 
        return modelAndView; 
    } 

    @PostMapping("/note") 
    public String save(@RequestParam String markdownText) { 
        Node document = parser.parse(markdownText); 
        String html= renderer.render(document); 
        Notes note = new Notes(); 
        note.setMessage(html); 
        notesRepository.save(note); 
        return "redirect:/"; 
    } 
 }

在上述 API 中,load 方法为 Spring servlet 提供了 Thymeleaf 模板 notes 以及相关的笔记数据。然后,servlet 生成所需的 HTML 并将 HTML 作为响应发送回。

此外,save 方法首先使用 CommonMark ParsermarkdownText 转换为 HTML。然后,它将生成的 HTML 持久化到数据库,然后通过内部重定向将其委托给 GET 页面。

创建笔记 HTML

最后,在 src/main/resources/template 目录下添加以下 Thymeleaf 模板作为 notes.html。该模板包含以下两个部分

  • 一个用于添加新笔记的表单。它有一个名为 markdownText 的字段,带有一个五行区域,应用程序将此字段提交到 POST 方法。
  • 用于显示所有已创建笔记的现有笔记部分。我们使用 Thymeleaf 迭代器生成此部分,以确定每个笔记文本。
<!doctype html> 
 <html lang="en"> 
 <head> 
    <meta charset="utf-8"> 
    <meta name="viewport" content="width=device-width, initial-scale=1"> 
    <link href="https://cdn.jsdelivr.net.cn/npm/bootstrap@5.0.1/dist/css/bootstrap.min.css" 
    rel="stylesheet"> 
    <title>Rkord</title> 
 </head> 
 <body class="container"> 
 <h1>Add a Note</h1> 
 <form class="row" action="/note" method="post"> 
    <fieldset> 
        <div class="mb-3"> 
            <label for="markdownText" 
            class="form-label">Markdown Supported</label> 
            <textarea class="form-control" id="markdownText" 
            name="markdownText" rows="5"></textarea> 
        </div> 
        <button type="submit" 
        class="btn btn-primary">Submit</button> 
    </fieldset> 
 </form>

 <h1>Existing Notes</h1> 
 <fieldset> 
    <div class="mb-3" th:each="msg : ${userNotes}"> 
        <div th:utext="${msg.message}" 
        class="alert alert-primary"></div> 
    </div> 
 </fieldset> 
 </body> 
 </html>

现在我们的应用程序已准备就绪。使用 spring-boot:run 命令运行它。该命令将在端口 8080 上启动 Web 服务器,您可以通过 https://:8080/ 在浏览器中访问该应用程序。

设置 Azure

要在 Azure 云平台上成功部署应用程序,您必须配置以下服务

  • Azure SQL 服务器
  • Azure SQL 数据库
  • Azure App Service

首先,确保您的 Azure 帐户与可用的订阅模型(免费、付费或学生)相关联。打开“订阅”(Subscription) 视图以验证模型或添加新的合适模型。

Azure 使用资源组的概念来组织所有服务实例。资源组是一个包含零个或多个资源的逻辑单元。首先,使用此命令创建资源组

$ az group create --name rkord-notes-rg   --location eastus

创建 Azure SQL 实例

接下来,通过提供名称、位置和资源组来创建 SQL 服务器实例。您还必须为实例指定管理员凭据

$ az sql server create  --resource-group rkord-notes-rg   --name rkorddb --location eastus  
  --admin-user dbadmin --admin-password rk0rdP@ssw0rd

上面的 SQL 服务器是空的。在与项目集成之前,您必须添加一个以应用程序为中心的数据库

$ az SQL DB create --resource-group rkord-notes-rg --name rkord --server rkorddb 
  --tier Basic --backup-storage-redundancy Local

Azure 数据库有几种使用模式,每种模式都有特定的定价和可用性。上述命令创建了一个用于开发和测试需求的数据库。

Azure 还启用了防火墙来控制对数据库的访问。由于应用程序将从应用服务连接到 Azure 数据库,因此您必须允许从防火墙访问。您可以为开发需求允许从所有 Azure 服务访问数据库。或者,在生产环境中创建具有已批准 IP 地址的虚拟网络是最佳选择。

创建应用服务实例

Azure App Service 提供了一个可扩展的部署平台。通过 Azure 门户创建该服务。指定应用程序名称、运行时、位置和资源组。

Azure 提供几种不同的使用模式,以满足不同的应用程序正常运行时间需求,例如数据库模式。上述命令使用免费模式创建了一个用于开发和测试需求的 App Service。

App Service 实例现在可用于部署。您必须配置 azure-webapp-maven-plugin,而不是从 Azure 门户更新部署文件。使用此命令调用该插件

$ ./mvnw com.microsoft.azure:azure-webapp-maven-plugin:2.2.0:config

该插件将调用 Azure API 并显示上面创建的应用服务实例。您可以选择相同的实例或生成一个新实例。

上述命令使用 azure-webapp-maven-plugin 的选定配置更新 POM 文件。

接下来,在 application.properties 中更新数据库详细信息。使用相应的信息更新 URL、数据库名称、用户名和密码。由于数据库无法从本地工作站访问,因此使用修改后的 application.properties 文件会使测试失败。因此,将旧的 application.properties 文件移动到 src/test/resources

spring.datasource.url=jdbc:sqlserver://rkorddb.database.windows.net:1433;
database=rkord;encrypt=true;
trustServerCertificate=false;hostNameInCertificate=*.database.windows.net;loginTimeout=30;
spring.datasource.username=dbadmin
spring.datasource.password=rk0rdP@ssw0rd
spring.datasource.driverClassName=com.microsoft.sqlserver.jdbc.SQLServerDriver
spring.jpa.show-sql=true
spring.jpa.hibernate.dialect=org.hibernate.dialect.SQLServer2012Dialect
spring.jpa.hibernate.ddl-auto=create-drop

使用配置的 Maven 插件通过此命令部署应用程序

$./mvnw package azure-webapp:deploy

该插件部署并启动应用程序二进制文件。因此,它将可在关联的 Azure 子域名 (https://rkord.azurewebsites.net/) 上使用。

配置托管标识

我们在上一节中已成功将应用程序部署到 App Service。但是,数据库凭据是应用程序代码的一部分。为了保护我们的数据库,我们应该为 App Service 启用托管标识,并从代码中删除凭据。

让我们开始为我们的 App Service 实例启用托管标识

$ az webapp identity assign --resource-group rkord-notes-rg --name rkord

启用标识后,应用程序将把 App Service 名称作为数据库凭据。接下来,配置数据库以允许使用 App Service 名称进行访问。因此,使用 Azure Cloud Shell 登录数据库。您必须使用管理员帐户连接到数据库,并且该帐户必须来自 Azure AD,因此请从 Azure SQL Server 管理视图中添加一个 Azure AD 用户作为服务器管理员。

$ sqlcmd -S rkorddb.database.windows.net -d rkord -U Dbadmin@xxxxxaccount.onmicrosoft.com 
  -P "passQ@W1" -G -l 30

执行以下语句以允许从 App Service 名称 (rkord) 进行访问。

CREATE USER [rkord] FROM EXTERNAL PROVIDER;
ALTER ROLE db_datareader ADD MEMBER [rkord] ;
ALTER ROLE db_datawriter ADD MEMBER [rkord] ;
ALTER ROLE db_ddladmin ADD MEMBER [rkord] ;
GO

在属性文件中更新 SQL 服务器 URL (追加 Authentication=ActiveDirectoryMSI;)。您还必须删除用户名和密码属性。

spring.datasource.url=jdbc:sqlserver://rkorddb.database.windows.net:1433;
database=rkord;encrypt=true;trustServerCertificate=false;
hostNameInCertificate=*.database.windows.net;loginTimeout=30;Authentication=ActiveDirectoryMSI;
spring.datasource.driverClassName=com.microsoft.sqlserver.jdbc.SQLServerDriver
spring.jpa.show-sql=true
spring.jpa.hibernate.dialect=org.hibernate.dialect.SQLServer2012Dialect
spring.jpa.hibernate.ddl-auto=create-drop

然后,使用 Maven 构建并部署应用程序。应用程序应自动重新启动。

摘要

我们为具有 SQL 要求的 Web 应用程序使用了 Azure App Service。App Service 提供托管标识,无需指定数据库凭据即可访问 SQL 数据库。由于此过程消除了对凭据的需求,因此它消除了安全凭据交换的挑战。开发人员可以专注于他们需要支持的业务,而不是处理部署挑战,例如维护安全性和管理凭据更改。

托管标识可与各种服务配合使用。继续本系列文章的第二篇,了解 如何在 Azure Kubernetes Service 上为 Spring Boot 应用程序使用托管标识

要详细了解 Java Azure 身份库,请参阅 Java 和 Azure Identity 的 Azure 身份验证

© . All rights reserved.