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

配置 Azure Static Web Apps

您可以在 staticwebapp.config.json 文件中定义Azure Static Web Apps 的配置,该文件控制以下设置:

注意

以前用于配置路由的 routes.json 已被启用。 使用本文中所述的 staticwebapp.config.json ,为静态 Web 应用配置路由和其他设置。

本文档描述如何配置 Azure Static Web Apps,它是一项独立的产品,与 Azure 存储的静态网站托管功能不同。

文件位置

建议将 staticwebapp.config.json 置于工作流文件中设置为 app_location 的文件夹内。 但是,可将该文件放在设置为 app_location 的文件夹的任何子文件夹中。 此外,如果有生成步骤,则必须确保生成步骤将文件输出到 output_location 的根目录。

有关详细信息,请参阅示例配置文件。

重要

如果 staticwebapp.config.json 存在,则会忽略已被弃用的 routes.json 文件

路由

可以在静态 Web 应用中为一个或多个路由定义规则。 路由规则允许仅限充当特定角色的用户进行访问,或执行重定向或重写等操作。 路由定义为路由规则的数组。 有关用法示例,请参阅示例配置文件

  • 即使只有一个路由,亦要在 routes 数组中定义规则。
  • 规则按照其在 routes 数组中的显示顺序进行评估。
  • 规则评估将在第一次匹配时停止。 当 route 属性和 methods 数组中的值(如果已指定)与请求匹配时表示匹配。 每个请求最多可以匹配一个规则。

路由问题在很大程度上与身份验证(识别用户的身份)和授权(为用户赋能)的概念息息相关。 务必要阅读身份验证和授权指南以及本文。

定义路由

每个规则都包含一个路由模式,以及一个或多个可选的规则属性。 在 routes 数组中定义了路由规则。 有关用法示例,请参阅示例配置文件

重要

只能使用 routemethods(如果已指定)属性来确定规则是否与请求匹配。

规则属性 必选 默认值 注释
route 不适用 调用方请求的路由模式。
  • 路由路径的末尾支持通配符
    • 例如,路由 /admin* 与任何以 /admin 开头的路由匹配。
methods 所有方法 定义与路由匹配的请求方法的数组。 可用方法包括:GETHEADPOSTPUTDELETECONNECTOPTIONSTRACEPATCH
rewrite 不适用 定义从请求返回的文件或路径。
  • redirect 规则互斥。
  • 重写规则不会更改浏览器的位置。
  • 值必须相对于应用程序的根目录。
redirect 不适用 定义请求的文件或路径重定向目标。
  • rewrite 规则互斥。
  • 重定向规则更改浏览器的位置。
  • 默认响应代码为 302(暂时重定向),但可以使用 301(永久重定向)进行替代。
statusCode 用于重定向的 301302 响应的 HTTP 状态代码
headers 不适用 添加到响应的一组 HTTP 头
  • 当路由特定的头与响应中的全局头相同时,路由特定的头将替代 globalHeaders
  • 若要删除头,请将值设置为空字符串。
allowedRoles 匿名 定义访问路由所需的角色名称数组。
  • 有效字符包括 a-zA-Z0-9_
  • 内置角色 anonymous,适用于所有用户。
  • 内置角色 authenticated 适用于任何已登录的用户。
  • 用户必须至少属于一个角色。
  • 角色在 OR 基础上进行匹配。
    • 如果用户处于列出的任何角色中,则授予访问权限。
  • 单个用户通过邀请关联到角色。

每个属性在请求/响应管道中都有特定的用途。

目的 属性
匹配路由 routemethods
匹配并授权规则后进行处理 rewrite(修改请求)

redirectheadersstatusCode(修改响应)
匹配路由后授权 allowedRoles

指定路由模式

route 属性可以是确切的路由或通配符模式。

确切的路由

若要定义确切的路由,请将文件的完整路径放在 route 属性中。

{
  "route": "/profile/index.html",
  "allowedRoles": ["authenticated"]
}

此规则匹配对文件 /profile/index.html 的请求。 由于 index.html 是默认文件,因此该规则还会匹配对文件夹(/profile 或 /profile/)的请求。

重要

如果在 route 属性中使用文件夹路径(/profile/profile/),则它不会匹配对文件 /profile/index.html 的请求。 在保护为文件提供服务的路由时,请始终使用文件的完整路径,例如 /profile/index.html

通配符模式

通配符规则匹配路由模式中的所有请求,仅支持在路径末尾使用。 有关用法示例,请参阅示例配置文件

例如,若要为日历应用程序实现路由,可以重写 calendar 路由下的所有 URL,以提供单个文件。

{
  "route": "/calendar*",
  "rewrite": "/calendar.html"
}

然后,calendar.html 文件可使用客户端路由为 URL 变体(如 /calendar/january/1/calendar/2020/calendar/overview)提供不同的视图。

注意

路由模式 /calendar/* 匹配 /calendar/ 路径下的所有请求。 但是,它不会匹配对路径 /calendar 或 /calendar.html 的请求。 使用 /calendar* 可以匹配以 /calendar 开头的所有请求。

可按文件扩展名筛选通配符匹配项。 例如,如果想要添加仅匹配给定路径中的 HTML 文件的规则,可以创建以下规则:

{
  "route": "/articles/*.html",
  "headers": {
    "Cache-Control": "public, max-age=604800, immutable"
  }
}

若要按多个文件扩展名进行筛选,请将选项括在大括号中,如以下示例中所示:

{
  "route": "/images/thumbnails/*.{png,jpg,gif}",
  "headers": {
    "Cache-Control": "public, max-age=604800, immutable"
  }
}

通配符路由的常见用例包括:

  • 为整个路径模式提供一个特定文件
  • 强制实施身份验证和授权规则
  • 实施专用缓存规则

使用角色保护路由

通过将一个或多个角色名称添加到规则的 allowedRoles 数组中来保护路由。 有关用法示例,请参阅示例配置文件

重要

传递规则只能保护向静态 Web 应用中提供的路由发出的 HTTP 请求。 许多前端框架都使用在浏览器中修改路由(不向静态 Web 应用发出请求)的客户端路由。 传递规则不保护客户端路由。 客户端应调用 HTTP API 来检索敏感数据。 确保 API 在返回数据之前先验证用户的标识

默认情况下,每个用户都属于内置 anonymous 角色,所有登录用户都是 authenticated 角色成员。 或者,用户通过邀请关联到自定义角色。

例如,若要将路由限制为仅经过身份验证的用户,请将内置 authenticated 角色添加到 allowedRoles 数组。

{
  "route": "/profile*",
  "allowedRoles": ["authenticated"]
}

可以根据需要在 allowedRoles 数组中创建新角色。 若要仅限管理员进行路由,可以在 allowedRoles 数组中定义自己的名为 administrator 的角色。

{
  "route": "/admin*",
  "allowedRoles": ["administrator"]
}
  • 你可以全面控制角色名称;不存在角色必须遵循的列表。
  • 单个用户通过邀请关联到角色。

重要

在保护内容时,请尽可能地指定确切的文件。 如果要保护许多文件,请在共享前缀后面使用通配符。 例如:/profile* 保护所有以 /profile 开头的可能路由,包括 /profile。

限制对整个应用程序的访问

通常需要对应用程序中的每一个路由要求进行身份验证。 若要锁定路由,请添加一个匹配所有路由的规则,并在 allowedRoles 数组中包含内置 authenticated 角色。

以下示例配置将阻止匿名访问,并将所有未经身份验证的用户重定向到 Microsoft Entra 登录页。

{
  "routes": [
    {
      "route": "/*",
      "allowedRoles": ["authenticated"]
    }
  ],
  "responseOverrides": {
    "401": {
      "statusCode": 302,
      "redirect": "/.auth/login/aad"
    }
  }
}

注意

默认情况下,所有预配置的标识提供者都为启用状态。 若要阻止身份验证提供程序,请参阅身份验证和授权

回退路由

单页应用程序通常依赖于客户端路由。 这些客户端路由规则无需向服务器发回请求即可更新浏览器的窗口位置。 如果刷新页面,或直接转到客户端路由规则生成的 URL,则需要服务器端回退路由来提供相应的 HTML 页面。 回退页通常被指定为客户端应用的 index.html

通过添加 navigationFallback 部分可定义回退规则。 以下示例针对所有与所部署的文件不匹配的静态文件请求返回 /index.html。

{
  "navigationFallback": {
    "rewrite": "/index.html"
  }
}

可通过定义筛选器来控制哪些请求返回回退文件。 在下面的示例中,对 /images 文件夹中的某些路由和 /css 文件夹中的所有文件的请求不会返回回退文件 。

{
  "navigationFallback": {
    "rewrite": "/index.html",
    "exclude": ["/images/*.{png,jpg,gif}", "/css/*"]
  }
}

例如,使用下面的目录结构,上述导航回退规则将导致下表中详述的结果。

├── images
│   ├── logo.png
│   ├── headshot.jpg
│   └── screenshot.gif
│
├── css
│   └── global.css
│
└── index.html
请求... 返回... 以及状态...
/about/ /index.html 文件。 200
/images/logo.png 图像文件。 200
/images/icon.svg /index.html 文件 - 因为 svg 文件扩展名未在 /images/*.{png,jpg,gif} 筛选器中列出。 200
/images/unknown.png “未找到文件”错误。 404
/css/unknown.css “未找到文件”错误。 404
/css/global.css 样式表文件。 200
/images/css 文件夹外部的任何其他文件 /index.html 文件。 200

重要

如果要从弃用的 routes.json 文件迁移,请勿在路由规则中包含旧版回退路由 ("route": "/*")。

全局头

globalHeaders 节提供一组应用于每个响应的 HTTP 头,除非由路由头规则替代,否则将从路由和全局头返回两个头的并集。

有关用法示例,请参阅示例配置文件

若要删除头,请将值设置为空字符串 ("")。

全局头的一些常见用例包括:

  • 自定义缓存规则
  • 安全策略
  • 编码设置
  • 跨域资源共享 (CORS) 配置

以下示例实施自定义 CORS 配置。

{
  "globalHeaders": {
    "Access-Control-Allow-Origin": "https://example.com",
    "Access-Control-Allow-Methods": "POST, GET, OPTIONS"
  }
}

注意

全局标头不影响 API 响应。 API 响应中的标头将保留并返回到客户端。

响应替代

responseOverrides 节中,可以定义当服务器返回错误代码时要做出的自定义响应。 有关用法示例,请参阅示例配置文件

可使用以下 HTTP 代码进行替代:

状态代码 含义 可能的原因
400 错误的请求 邀请链接无效
401 未授权 在未经身份验证的情况下请求访问受限页面
403 禁止
  • 用户已登录,但没有所需的角色,无法查看该页面。
  • 用户已登录,但运行时无法从其标识声明中获取用户详细信息。
  • 有太多的用户使用自定义角色登录到站点,因此运行时无法将该用户登录。
404 未找到 找不到文件

以下示例配置演示如何替代错误代码。

{
  "responseOverrides": {
    "400": {
      "rewrite": "/invalid-invitation-error.html"
    },
    "401": {
      "statusCode": 302,
      "redirect": "/login"
    },
    "403": {
      "rewrite": "/custom-forbidden-page.html"
    },
    "404": {
      "rewrite": "/custom-404.html"
    }
  }
}

平台

platform 部分控制特定于平台的设置,例如 API 语言运行时版本。

选择 API 语言运行时版本

若要配置 API 语言运行时版本,请将 platform 部分中的 apiRuntime 属性设置为以下支持的值之一。

语言运行时版本 操作系统 Azure Functions 版本 apiRuntime 支持结束日期
.NET Core 3.1 Windows 3.x dotnet:3.1 2022 年 12 月 3 日
.NET 6.0(进程内) Windows 4.x dotnet:6.0 -
.NET 6.0(独立) Windows 4.x dotnet-isolated:6.0 -
.NET 7.0(独立) Windows 4.x dotnet-isolated:7.0 -
.NET 8.0 独立 Windows 4.x dotnet-isolated:8.0 -
Node.js 12.x Linux 3.x node:12 2022 年 12 月 3 日
Node.js 14.x Linux 4.x node:14 -
Node.js 16.x Linux 4.x node:16 -
Node.js 18.x Linux 4.x node:18 -
Python 3.8 Linux 4.x python:3.8 -
Python 3.9 Linux 4.x python:3.9 -
Python 3.10 Linux 4.x python:3.10 -

.NET

若要更改 .NET 应用中的运行时版本,请更改 csproj 文件中的 TargetFramework 值。 (可选)如果在 staticwebapp.config.json 文件中设置了一个 apiRuntime 值,请确保该值与你在 csproj 文件中定义的值相匹配。

以下示例演示如何将 NET 8.0 的 TargetFramework 元素更新为 csproj 文件中的 API 语言运行时版本

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
    ...
  </PropertyGroup>
...

Node.js

以下示例配置演示如何使用 apiRuntime 属性在 staticwebapp.config.json 文件中选择 Node.js 16 作为 API 语言运行时版本

{
  ...
  "platform": {
    "apiRuntime": "node:16"
  }
  ...
}

Python

以下示例配置演示如何使用 apiRuntime 属性在 staticwebapp.config.json 文件中选择 Python 3.8 作为 API 语言运行时版本

{
  ...
  "platform": {
    "apiRuntime": "python:3.8"
  }
  ...
}

网络

networking 部分控制静态 Web 应用的网络配置。 若要限制对应用的访问,请在 allowedIpRanges 中指定允许的 IP 地址块的列表。 有关允许的 IP 地址块数的详细信息,请参阅 Azure Static Web Apps 中的配额

注意

只能在 Azure Static Web Apps 标准计划中使用网络配置。

采用无类别域际路由选择 (CIDR) 表示法定义每个 IPv4 地址块。 若要详细了解 CIDR 表示法,请参阅无类别域际路由选择。 每个 IPv4 地址块都可以表示公共地址空间或专用地址空间。 如果只需从单个 IP 地址访问,可以使用 /32 CIDR 块。

{
  "networking": {
    "allowedIpRanges": [
      "10.0.0.0/24",
      "100.0.0.0/32",
      "192.168.100.0/22"
    ]
  }
}

指定一个或多个 IP 地址块时,从与 allowedIpRanges 中值不匹配的 IP 地址发起的请求将被拒绝访问。

除 IP 地址块外,还可指定 allowedIpRanges 数组中的服务标记来限制流向某些 Azure 服务的流量。

"networking": {
  "allowedIpRanges": ["AzureFrontDoor.Backend"]
}

身份验证

若要详细了解如何将路由限制为经过身份验证的用户,请参阅使用角色保护路由

为经过身份验证的路径禁用缓存

如果已设置了与 Azure Front Door 的手动集成,则可能需要为安全路由禁用缓存。 启用企业级边缘后,安全路由已禁用缓存。

若要为安全路由禁用 Azure Front Door 缓存,请将 "Cache-Control": "no-store" 添加到路由标头定义。

例如:

{
    "route": "/members",
    "allowedRoles": ["authenticated, members"],
    "headers": {
        "Cache-Control": "no-store"
    }
}

转发网关

forwardingGateway 部分配置如何从转发网关(例如内容分发网络 (CDN) 或 Azure Front Door)访问静态 Web 应用。

注意

只能在 Azure Static Web Apps 标准计划中使用转发网关配置。

允许转发的主机

allowedForwardedHosts 列表指定要在 X-Forwarded-Host 标头中接受的主机名。 如果列表中有匹配的域,Static Web Apps 在构造重定向 URL 时(如成功登录后)将使用 X-Forwarded-Host 值。

为了使 Static Web Apps 在转发网关后正常运行,来自网关的请求必须在 X-Forwarded-Host 标头中包含正确的主机名,该主机名必须在 allowedForwardedHosts 中列出。

"forwardingGateway": {
  "allowedForwardedHosts": [
    "example.org",
    "www.example.org",
    "staging.example.org"
  ]
}

如果 X-Forwarded-Host 标头与列表中的值不匹配,请求仍会成功,但响应中不会使用此标头。

必需标头

必需的标头是必须与每个请求一起发送到你的站点的 HTTP 标头。 必需的标头的一种用途是拒绝对站点的访问,除非每个请求中都有所有必需的标头。

例如,以下配置演示如何添加 Azure Front Door 的唯一标识符,以限制从特定 Azure Front Door 实例对站点的访问。 有关完整的详细信息,请参阅配置 Azure Front Door 教程

"forwardingGateway": {
  "requiredHeaders": {
    "X-Azure-FDID" : "692a448c-2b5d-4e4d-9fcc-2bc4a6e2335f"
  }
}
  • 键/值对可以是任意字符串集
  • 键不区分大小写
  • 值区分大小写

尾随斜杠

尾随斜杠是 URL 末尾的 /。 通常,尾随斜杠 URL 是指 Web 服务器上的目录,而非尾随斜杠 URL 则表示文件。

无论是文件还是目录,搜索引擎都会分开处理这两种 URL。 在这两种 URL 中呈现相同的内容时,你的网站会提供对搜索引擎优化 (SEO) 产生负面影响的重复内容。 显式配置后,Static Web Apps 会应用一组 URL 规范化和重定向规则,以帮助改进网站的性能和 SEO。

以下规范化和重定向规则适用于每个可用配置:

始终

trailingSlash 设置为 always 时,不包含尾随斜杠的所有请求都会重定向到尾随斜杠 URL。 例如,/contact 会重定向到 /contact/

"trailingSlash": "always"
请求... 返回... 以及状态... 路径...
/about /about/index.html 文件 301 /about/
/about/ /about/index.html 文件 200 /about/
/about/index.html /about/index.html 文件 301 /about/
/contact /contact.html 文件 301 /contact/
/contact/ /contact.html 文件 200 /contact/
/contact.html /contact.html 文件 301 /contact/

从不

trailingSlash 设置为 never 时,以尾随斜杠结尾的所有请求都会重定向到非尾随斜杠 URL。 例如,/contact/ 会重定向到 /contact

"trailingSlash": "never"
请求... 返回... 以及状态... 路径...
/about /about/index.html 文件 200 /about
/about/ /about/index.html 文件 301 /about
/about/index.html /about/index.html 文件 301 /about
/contact /contact.html 文件 200 /contact
/contact/ /contact.html 文件 301 /contact
/contact.html /contact.html 文件 301 /contact

Auto

trailingSlash 设置为 auto 时,对文件夹的所有请求都会重定向到带尾随斜杠的 URL。 对文件的所有请求都会重定向到非尾随斜杠 URL。

"trailingSlash": "auto"
请求... 返回... 以及状态... 路径...
/about /about/index.html 文件 301 /about/
/about/ /about/index.html 文件 200 /about/
/about/index.html /about/index.html 文件 301 /about/
/contact /contact.html 文件 200 /contact
/contact/ /contact.html 文件 301 /contact
/contact.html /contact.html 文件 301 /contact

为了获得最佳网站性能,请使用 alwaysneverauto 模式中的一种配置尾随斜杠策略。

默认情况下,当省略 trailingSlash 配置时,Static Web Apps 会应用以下规则:

请求... 返回... 以及状态... 路径...
/about /about/index.html 文件 200 /about
/about/ /about/index.html 文件 200 /about/
/about/index.html /about/index.html 文件 200 /about/index.html
/contact /contact.html 文件 200 /contact
/contact/ /contact.html 文件 301 /contact
/contact.html /contact.html 文件 200 /contact.html

示例配置文件

{
  "trailingSlash": "auto",
  "routes": [
    {
      "route": "/profile*",
      "allowedRoles": ["authenticated"]
    },
    {
      "route": "/admin/index.html",
      "allowedRoles": ["administrator"]
    },
    {
      "route": "/images/*",
      "headers": {
        "cache-control": "must-revalidate, max-age=15770000"
      }
    },
    {
      "route": "/api/*",
      "methods": ["GET"],
      "allowedRoles": ["registeredusers"]
    },
    {
      "route": "/api/*",
      "methods": ["PUT", "POST", "PATCH", "DELETE"],
      "allowedRoles": ["administrator"]
    },
    {
      "route": "/api/*",
      "allowedRoles": ["authenticated"]
    },
    {
      "route": "/customers/contoso*",
      "allowedRoles": ["administrator", "customers_contoso"]
    },
    {
      "route": "/login",
      "rewrite": "/.auth/login/github"
    },
    {
      "route": "/.auth/login/twitter",
      "statusCode": 404
    },
    {
      "route": "/logout",
      "redirect": "/.auth/logout"
    },
    {
      "route": "/calendar*",
      "rewrite": "/calendar.html"
    },
    {
      "route": "/specials",
      "redirect": "/deals",
      "statusCode": 301
    }
  ],
  "navigationFallback": {
    "rewrite": "index.html",
    "exclude": ["/images/*.{png,jpg,gif}", "/css/*"]
  },
  "responseOverrides": {
    "400": {
      "rewrite": "/invalid-invitation-error.html"
    },
    "401": {
      "redirect": "/login",
      "statusCode": 302
    },
    "403": {
      "rewrite": "/custom-forbidden-page.html"
    },
    "404": {
      "rewrite": "/404.html"
    }
  },
  "globalHeaders": {
    "content-security-policy": "default-src https: 'unsafe-eval' 'unsafe-inline'; object-src 'none'"
  },
  "mimeTypes": {
    ".json": "text/json"
  }
}

根据上述配置查看以下场景。

请求... 结果...
/profile 向经过身份验证的用户提供 /profile/index.html 文件。 未经身份验证的用户将根据 401 响应替代规则重定向到 /login。
/admin、/admin/ 或 /admin/index.html 为充当 administrator 角色的经过身份验证的用户提供 /admin/index.html 文件。 为不充当 administrator 角色的经过身份验证的用户提供 403 错误 1。 未经身份验证的用户将重定向到 /login。
/images/logo.png 使用自定义缓存规则提供图像,该规则中的最大期限略微超过 182天(15,770,000 秒)。
/api/admin 将充当 registeredusers 角色的经过身份验证的用户发来的 GET 请求发送到 API。 为不充当 registeredusers 角色的经过身份验证的用户以及未经过身份验证的用户提供 401 错误。

将充当 administrator 角色的经过身份验证的用户发来的 POSTPUTPATCHDELETE 请求发送到 API。 为不充当 administrator 角色的经过身份验证的用户以及未经过身份验证的用户提供 401 错误。
/customers/contoso 为属于 administrator 或 customers_contoso 角色的经过身份验证的用户提供 /customers/contoso/index.html 文件 。 为不充当 administrator 或 customers_contoso 角色的经过身份验证的用户提供 403 错误1 。 未经身份验证的用户重定向到 /login
/login 未经身份验证的用户将面临在 GitHub 中进行身份验证的挑战。
/.auth/login/twitter 由于路由规则禁用 Twitter 授权,因此将返回 404 错误。 然后,此错误会回退到使用 200 状态代码提供 /index.html
/logout 用户已注销任何身份验证提供程序。
/calendar/2021/01 将向浏览器提供 /calendar.html 文件。
/specials 浏览器永久重定向到 /deals
/data.json 提供 text/json MIME 类型的文件。
/about,或与客户端路由模式匹配的任何文件夹 提供 /index.html 文件和 200 状态代码。
/images/ 文件夹中不存在的文件 404 错误。

1 可以使用响应替代规则提供自定义错误页。

限制

staticwebapp.config.json 文件存在以下限制。

  • 最大文件大小为 20 KB
  • 最多 50 个不同角色

有关一般限制和局限性,请参阅有关配额的文章

后续步骤