@Configuration(proxyBeanMethods = false)
@EnableWebSecurity
@EnableMethodSecurity
public class AadOAuth2LoginSecurityConfig {
@Bean
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.apply(AadWebApplicationHttpSecurityConfigurer.aadWebApplication())
.and()
.authorizeHttpRequests()
.requestMatchers(EndpointRequest.to("health")).permitAll()
.anyRequest().authenticated()
.and()
.logout(logout -> logout
.deleteCookies("JSESSIONID", "XSRF-TOKEN")
.clearAuthentication(true)
.invalidateHttpSession(true));
return http.build();
有关详细信息,请参阅:
将应用程序注册到 Microsoft 标识平台
AppRoles 属性
适用于 Microsoft Entra 的 Spring Boot 启动器开发人员指南
将使用 Microsoft Entra 帐户登录添加到 Spring Web 应用
将应用角色添加到应用程序中并在令牌中接收它们
可配置令牌在 Microsoft 标识平台中的生存期
配置服务身份验证和授权,以便环境中的服务具有执行必要功能的权限。 使用 Microsoft Entra ID 中的托管标识自动创建和管理服务标识,从而消除手动凭据管理。 托管标识允许 Web 应用安全地访问 Azure 服务,例如 Azure Key Vault 和数据库。 它还有助于 CI/CD 管道集成,用于部署到 Azure App Service。 但是,混合部署或旧版系统等方案中仍继续使用本地身份验证解决方案来简化迁移。 当系统准备好采用现代标识管理方法时,转换到托管标识。 有关详细信息,请参阅监视托管标识。
示例:参考实现保留数据库的本地身份验证机制(用户名和密码)。 因此,参考实现将数据库机密存储在密钥保管库中。 Web 应用使用(系统分配的)托管标识在密钥保管库中检索机密。
使用中央机密存储来管理机密
将应用程序转移到云端时,请使用 Azure Key Vault 安全地存储所有此类机密。 此集中式存储库为不支持托管标识的服务提供安全存储、密钥轮换、访问审核和监视。 对于应用程序配置,建议采用 Azure App Configuration。
示例:参考实现在密钥保管库中存储以下机密:(1) PostgreSQL 数据库用户名和密码,(2) Redis 缓存密码,以及 (3) 与 MSAL 实现关联的 Microsoft Entra ID 的客户端密码。
不要将密钥保管库置于 HTTP 请求流中
在应用程序启动时(而不是在每个 HTTP 请求期间)从密钥保管库加载机密。 密钥保管库用于在部署期间安全地存储和检索敏感数据。 HTTP 请求中的高频率访问可能会超过密钥保管库的吞吐容量,从而导致请求限制和 HTTP 状态代码 429 错误。 更多信息请参阅《密钥保管库事务限制》。
使用一种方法访问密钥保管库中的机密
有两个主要选项可配置 Web 应用以访问密钥保管库中的机密:
应用程序服务应用设置:使用应用程序服务中的应用设置将机密直接注入为环境变量。
直接机密引用:直接引用应用程序代码中的机密。 在应用程序的属性文件(例如适用于 Java 应用程序的 application.properties
)中添加特定引用,以便应用与密钥保管库通信。
为简单起见,请务必选择其中一种方法并坚持使用,以避免不必要的复杂性。 若要将密钥保管库与 Spring 应用程序集成,此过程涉及:
在 pom.xml 文件中为 Azure Key Vault 机密依赖项添加 Azure Spring Boot Starter。
在应用程序中配置密钥保管库终结点。 这可以通过 application.properties 文件或作为环境变量来完成。
示例:参考实现在应用程序服务中使用应用设置并注入机密。
使用专用终结点
在所有生产环境中为所有受支持的 Azure 服务使用专用终结点。 专用终结点为 Azure 虚拟网络资源和 Azure 服务提供专用连接。 默认情况下,与大多数 Azure 服务的通信会跨公共网络。 专用终结点不需要任何代码更改、应用配置或连接字符串。 有关详细信息,请参阅如何创建专用终结点和确保终结点安全的最佳做法。
示例:参考实现为 Key Vault、Azure Cache for Redis 和 Azure Database for PostgreSQL 使用专用终结点。
使用 Web 应用程序防火墙
发往 Web 应用的所有入站 Internet 流量都必须通过 Web 应用程序防火墙,以防止常见的 Web 攻击。 强制所有入站 Internet 流量通过公共负载均衡器(如果有)和 Web 应用程序防火墙。 可以 (1) 使用 Azure Front Door 专用终结点,也可以 (2) 按 X-Azure-FDID
标头值筛选请求。
Azure 应用服务平台和 Java Spring 可以按标头值进行筛选。 首选应使用 Azure 应用服务。 在平台级别进行筛选可防止不需要的请求获得代码。 需要配置要通过 Web 应用程序防火墙的流量。 可以根据主机名、客户端 IP 和其他值进行筛选。 有关详细信息,请参阅保留原始 HTTP 主机名。
示例:参考实现在生产环境中使用专用终结点,X-Azure-FDID
在开发环境中使用标头值。
对数据库的管理员级别访问权限授予执行特权操作的权限。 特权操作包括创建和删除数据库、修改表架构或更改用户权限。 开发人员通常需要管理员级访问权限来维护数据库或排查问题。
避免永久提升权限。 授予开发人员执行特权操作的实时访问权限。 通过实时访问,用户将获得临时权限来执行特权任务。
请勿授予应用程序提升的权限。 不要授予对应用程序标识的管理员级访问权限。 为应用程序配置对数据库的最小特权访问。 如此可以限制 bug 和安全漏洞的爆发半径。 有两种主要方法可以访问 Azure PostgreSQL 数据库。 可以使用 Microsoft Entra 身份验证或 PostgreSQL 身份验证。 更多信息请参阅《JDBC 与 Azure PostgreSQL 配合使用》。
成本优化是寻找方法来减少不必要的费用和管理开销。 有关详细信息,请参阅成本优化设计评审核对清单。 可靠 Web 应用模式通过合理精简技术、自动缩放和高效资源使用来实现成本更优化的 Web 应用。
针对每个环境调整资源大小
了解 Azure 服务的不同性能层,并仅使用相应的 SKU 来满足每个环境的需求。 生产环境需要满足生产所需的服务级别协议 (SLA)、功能和规模的 SKU。 非生产环境通常不需要相同的功能。 若要节省额外成本,请考虑 Azure 开发/测试定价选项、Azure 预留和用于计算的 Azure 节省计划。
示例:参考实现不使用不涵盖任何组件的 Azure 开发/测试定价。 如果计划在云阶段的初始收敛后至少使用一年数据库引擎,那么 Azure Database for PostgreSQL 是首要适合预留实例的选项。 参考实现具有部署其他 SKU 的可选参数。 环境参数指示 Terraform 模板选择开发 SKU。 以下代码演示此环境参数。
azd env set APP_ENVIRONMENT prod
Contoso Fiber 使用基础结构即代码 (IaC) 模板进行开发和生产部署。 开发环境经过成本优化,使用成本最低的 SKU 进行应用开发。 生产环境使用的 SKU 满足应用程序生产服务级别目标要求。
使用自动缩放
自动缩放可为生产环境自动执行横向缩放。 按性能指标自动缩放。 如果你不了解应用程序的缩放条件,CPU 使用率性能触发器是一个很好的起点。 需要配置和调整缩放触发器(CPU、RAM、网络和磁盘)以与 Web 应用程序的行为相对应。 不要垂直缩放以满足经常变化的需求。 它的成本效益较低。 有关详细信息,请参阅在 Azure 应用服务中进行缩放和在 Microsoft Azure 中进行自动缩放。
有效使用资源
有效的资源使用涉及云资源的战略管理和分配,以满足组织需求,而不会产生浪费。 它将不必要的资源支出和管理开销降到最低。 若要提高资源效率,请遵循以下建议:
使用共享服务。 集中和共享某些资源可提供成本优化和较低的管理开销。 例如,将共享网络资源置于中心虚拟网络中。
删除未使用的环境。 在下班后或节假日期间删除非生产环境,以优化成本。 可以使用基础结构即代码删除 Azure 资源和整个环境。 删除要从基础结构即代码模板中删除的资源的声明。 备份日后需要使用的数据。 了解要删除的资源的依赖项。 如果有依赖项,则可能需要更新或删除这些资源。
并置功能。 如果有备用容量,可将应用程序资源和功能并置在单个 Azure 资源上。 例如,多个 Web 应用可以使用单个服务器(应用服务计划),或者单个缓存可以支持多种数据类型。
卓越运营涵盖了部署应用程序并使其在生产环境中保持运行的运营流程。 有关详细信息,请参阅设计卓越运营的审查清单。 可靠 Web 应用模式为基础结构部署实现基础结构即代码,并监视可观测性。
应启用日志记录进行追踪和调试,以便随时在请求失败时进行诊断。 从应用程序收集的遥测应满足其操作需求。 至少必须收集有关基线指标的遥测数据。 你应收集能协助进行针对性改进的用户行为信息。
监视基线指标
工作负载应监视基线指标。 要度量的重要指标包括请求吞吐量、平均请求持续时间、错误和依赖项监视。 建议使用 Application Insights 来收集遥测数据。
示例:参考实现使用 Application Insights。 Application Insights 通过 Terraform 作为应用程序服务的 app_settings 配置的一部分启用。
app_settings = {
APPLICATIONINSIGHTS_CONNECTION_STRING = var.app_insights_connection_string
ApplicationInsightsAgent_EXTENSION_VERSION = "~3"
Spring Boot 在 Application Insights 上显示多个核心指标,例如 Java 虚拟机 (JVM) 、CPU、Tomcat 等。 Application Insights 会自动从 Log4j 和 Logback 等日志记录框架上进行收集。 有关详细信息,请参阅:
为 Spring Boot 配置 Azure Monitor Application Insights
配置选项 - 适用于 Java 的 Azure Monitor Application Insights - Azure Monitor
为 Java 应用程序启用 Azure Monitor OpenTelemetry
将 Azure Monitor Application Insights 与 Spring Boot 配合使用。
根据需要创建自定义遥测和指标
除了 Application Insights 中的基线指标外,还应创建自定义遥测,以便更好地了解用户及其与应用程序的互动。 Application Insights 可以收集自定义遥测数据,你还可以通过 Micrometer 收集自定义指标。 目标是更深入地了解应用程序的性能和用户行为,以便做出更明智的决策和改进。
收集基于日志的指标
跟踪基于日志的指标,以便更好地了解基本应用程序运行状况和指标。 可以在 Application Insights 中使用 Kusto 查询语言 (KQL) 查询来查找和整理数据。 更多信息请参阅《基于 Azure Application Insights 日志的指标》和《Application Insights 中基于日志的预先聚合指标》。
Azure 的诊断设置可以指定要收集的平台日志和指标及其存储位置。 平台日志为内置日志,可以提供诊断和审核信息。 你可以为大多数 Azure 服务启用平台诊断,但每个服务有其自己的日志类别。 不同的 Azure 服务可以选择不同的日志类别。
为所有受支持的服务启用诊断。 Azure 服务会自动创建平台日志,但不会自动存储日志。 必须为每个服务启用诊断设置,并且应为每个支持诊断的 Azure 服务启用诊断设置。
将诊断发送到与应用程序日志相同的目的地。 启用诊断时,可以选择要收集的日志及其发送目的地。 应将平台日志和应用程序日志发送到相同的目的地,以便关联两个数据集。
示例:参考实现使用 Terraform 对所有受支持的服务启用 Azure 诊断。 以下 Terraform 代码配置应用程序服务的诊断设置。
# Configure Diagnostic Settings for App Service
resource "azurerm_monitor_diagnostic_setting" "app_service_diagnostic" {
name = "app-service-diagnostic-settings"
target_resource_id = azurerm_linux_web_app.application.id
log_analytics_workspace_id = var.log_analytics_workspace_id
#log_analytics_destination_type = "AzureDiagnostics"
enabled_log {
category_group = "allLogs"
metric {
category = "AllMetrics"
enabled = true
使用 CI/CD 管道
若要自动执行部署,请集成持续集成/持续部署 (CI/CD) 管道。 此自动化应直接从源代码管理扩展到各种应用程序服务环境,包括测试、暂存和生产。 如果使用的是适用于 GitHub 项目的 Azure DevOps 或 GitHub Actions,则使用 Azure Pipelines。
集成单元测试 在部署到应用程序服务之前,在管道中设置所有单元测试(使用 JUnit)的执行和传递优先级。 合并代码质量和覆盖率工具(如 SonarQube 和 JaCoCo)以实现全面的测试覆盖率。
采用 Java 模拟框架。 对于涉及外部终结点的测试,请使用 Java 模拟框架(Mockito、EasyMock)。 这些框架可创建模拟终结点。 无需配置真正的外部终结点,并确保跨环境提供统一的测试条件。
执行安全扫描。 使用静态应用程序安全测试 (SAST) 在源代码中查找安全漏洞和编码错误。 此外,执行软件组合分析 (SCA),检查第三方库和组件是否存在安全风险。 执行这些分析的工具可以轻松集成到 GitHub 和 Azure DevOps 中。
管理生产部署
需要建立将代码部署到生产环境的准则,并为所有生产部署创建审批流程。
性能效率是指工作负荷能够以高效的方式扩展以满足用户对它的需求。 有关详细信息,请参阅设计性能效率审查清单。 可靠 Web 应用模式使用缓存端模式来最大程度地减少高需求数据的延迟。
使用缓存端模式
缓存端模式是一种缓存策略,可改进内存中数据管理。 该模式为应用程序分配处理数据请求的责任,并确保缓存与持久性存储(例如数据库)之间的一致性。 当 Web 应用收到数据请求时,会首先搜索缓存。 如果数据缺失,将从数据库检索数据、响应请求并相应地更新缓存。 此方法可缩短响应时间并提高吞吐量,并减少缩放需求。 还通过减少主数据存储上的负载并最大程度地降低服务中断风险来提高服务可用性。
若要启用缓存,请将 spring-boot-starter-cache
包作为依赖项添加到 pom.xml
文件中。 spring-boot-starter-cache
包使用默认值配置 Redis 缓存。 应更新 application.properties
文件或环境变量中的上述值,以满足 Web 应用的需求。 例如, spring.cache.redis.time-to-live
(以毫秒计)决定了数据在被逐出之前在缓存中保留的时间。 你需要提供一个满足 Web 应用需求的值。 最后,需要使用 @Cacheable
注释在代码中缓存所需的数据。
缓存高需求数据
优先缓存最常访问的数据。 确定提高用户参与度和系统性能的关键数据点。 专门针对这些领域实施缓存策略,以提高缓存端模式的有效性,显著减少延迟和数据库负载。 使用 Azure Monitor 跟踪数据库的 CPU、内存和存储。 这些指标可帮助确定是否可以使用较小的数据库 SKU。
使缓存数据保持最新
计划定期缓存更新,以便与最新的数据库更改保持同步。 根据数据波动性和用户需求确定最佳刷新率。 这种做法可确保应用程序使用缓存端模式提供快速访问和最新信息。
确保数据一致性
实施各种机制以在任何数据库写入操作后立即更新缓存。 使用事件驱动的更新或专用数据管理类来确保缓存一致性。 始终将缓存与数据库修改保持同步是缓存端模式的核心。
示例:以下代码将 spring-boot-starter-cache
包作为依赖项添加到 pom.xml
文件以启用缓存。
<dependency>
<groupid>org.springframework.boot</groupid>
<artifactid>spring-boot-starter-cache</artifactid>
</dependency>
参考实现可在 application.properties
文件中启用 Redis。
# Redis
spring.data.redis.ssl.enabled=true
spring.session.redis.namespace=spring:session
以下代码代表名为 getAccountDetail
的方法。 该方法使用给定的用户名检索用户设置。 @Cacheable(value="account-details", key="#id")
对 getAccountDetail
方法进行批注并告知 Web 应用在暂存区缓存用户设置。
@Cacheable(value="account-details", key="#id")
public AccountDetail getAccountDetail(Long id) {
Optional<Account> optionalAccount = accountRepository.findById(id);
if (optionalAccount.isEmpty()) {
throw new IllegalArgumentException("Account ID " + id + " does not exist");
Account account = optionalAccount.get();
AccountDetail accountDetail = mapToAccountDetail(account);
return accountDetail;
数据库性能会影响应用程序的性能和可伸缩性。 请务必测试数据库性能,以确保其得到优化。 一些关键注意事项包括选择正确的云区域、连接池、缓存端模式和优化查询。
测试网络跃点。 将应用程序移动到云可能会给数据库带来额外的网络跃点和延迟。 应测试新云环境引入的额外跃点。
建立性能基线。 应使用本地性能指标作为初始基线,来比较云中的应用程序性能。
使用 Application Insights。 Application Insights 提供有关数据库查询和任何 JDBC 接口的详细指标。 应用于确保移植的数据库符合其 SLA 或查找需要优化的查询。 切勿使用动态 SQL,因为它会产生安全性和性能问题。
使用连接池。 应使用 JDBC 连接池,并根据每秒事务数 (TPS) 指标和 SLA 对其进行微调。 应使用数据库性能监视工具来测试和评估负载下的数据库性能。
按照 GitHub 存储库中的说明部署参考实现。 使用以下资源详细了解云最佳实践和迁移。
云最佳做法。 有关 Azure 采用和体系结构指南,请参阅:
云采用框架。 一个帮助组织准备和执行策略,以便在 Azure 上生成解决方案的框架。
架构良好的框架。 一套可用于改善工作负载质量的指导原则。
对于有更高服务级别目标 (SLO) 的应用程序,请参阅《任务关键型工作负载》。
迁移指导。 以下工具和资源可帮助你将本地资源迁移到 Azure:
Azure Migrate 为 Azure 提供简化的迁移、现代化和优化服务,用于处理 Web 应用、SQL Server 和虚拟机的评估和迁移。
Azure 数据库迁移指南提供适用于不同数据库类型的资源,和针对迁移方案设计的各式工具。
Azure 应用服务登陆区域加速器提供了强化和缩放应用服务部署的指导。
即将发布:在整个 2024 年,我们将逐步淘汰作为内容反馈机制的“GitHub 问题”,并将其取代为新的反馈系统。 有关详细信息,请参阅:https://aka.ms/ContentUserFeedback。
提交和查看相关反馈