ASP.NET Core Blazor WebAssembly .NET 运行时和应用捆绑包缓存
注意
此版本不是本文的最新版本。 对于当前版本,请参阅此文的 .NET 8 版本。
警告
此版本的 ASP.NET Core 不再受支持。 有关详细信息,请参阅 .NET 和 .NET Core 支持策略。 对于当前版本,请参阅此文的 .NET 8 版本。
当 Blazor WebAssembly 应用程序在浏览器中加载时,该应用程序将从服务器下载启动资源:
- 用于启动应用程序的 JavaScript 代码
- .NET 运行时和程序集
- 区域设置特定的数据
除了 Blazor 的启动资源文件 (blazor.boot.json
) 外,WebAssembly .NET 运行时和应用捆绑包文件都缓存在客户端上。 blazor.boot.json
文件包含构成必须下载的应用的文件清单,以及用于检测任何启动资源是否已被更改的文件内容的哈希。 Blazor 使用浏览器缓存 API 缓存下载的文件。
当 Blazor WebAssembly 下载应用的启动文件时,它会指示浏览器对响应执行完整性检查。 Blazor 为 DLL (.dll
)、WebAssembly (.wasm
) 和 blazor.boot.json
文件中的其他文件发送 SHA-256 哈希值。 缓存的文件的文件哈希与 blazor.boot.json
文件中的哈希进行比较。 对于具有匹配哈希的缓存文件,Blazor 使用缓存的文件。 否则,会从服务器请求文件。 在一个文件下载完成后,它的哈希值会被再次检查以验证完整性。 如果任何已下载文件的完整性检查失败,浏览器会生成错误。
Blazor 用于管理文件完整性的算法:
- 确保应用不会出现加载不一致文件集的风险,例如,在用户正在下载应用程序文件时,将新部署应用到 Web 服务器的情况。 不一致的文件可能会导致应用出现故障。
- 确保用户的浏览器从不缓存不一致或无效的响应,这些响应可阻止应用启动,即使用户手动刷新页面也是如此。
- 可以安全地缓存响应,在预期的 SHA-256 哈希本身发生更改之前,不检查服务器端更改,这使得后续页面加载涉及更少的请求,可以快速完成。
如果 Web 服务器返回的响应与预期的 SHA-256 哈希不匹配,类似于以下示例的错误将显示在浏览器的开发人员控制台中:
未能使用计算出的 SHA-256 完整性“IIa70iwvmEg5WiDV17OpQ5eCztNYqL186J56852RpJY=”在资源“https://myapp.example.com/_framework/MyBlazorApp.dll”的“integrity”属性中找到有效摘要。 资源已被阻止。
在大多数情况下,警告并不表示完整性检查存在问题。 相反,警告通常表示存在一些其他问题。
注意
指向 .NET 参考源的文档链接通常会加载存储库的默认分支,该分支表示针对下一个 .NET 版本的当前开发。 若要为特定版本选择标记,请使用“切换分支或标记”下拉列表。 有关详细信息,请参阅如何选择 ASP.NET Core 源代码的版本标记 (dotnet/AspNetCore.Docs #26205)。
诊断完整性问题
生成应用时,生成的 blazor.boot.json
清单将描述生成输出生成时启动资源的 SHA-256 哈希。 只要 blazor.boot.json
中的 SHA-256 哈希与传递到浏览器的文件相匹配,完整性检查就会通过。
此失败的常见原因包括:
- Web 服务器的响应是一个错误(例如,“404 - 找不到”或“500 - 内部服务器错误”),而不是浏览器所请求的文件。 浏览器会将其报告为完整性检查失败,而不是响应失败。
- 在文件生成和传递到浏览器之间已更改文件的内容。 下面可能会发生这种情况:
- 你或生成工具手动修改生成输出的情况。
- 部署过程的某个方面修改了文件的情况。 例如,在使用基于 Git 的部署机制时,请记住,如果你在 Windows 上提交文件并在 Linux 上检查它们,则 Git 会以透明方式将 Windows 样式的行尾转换为 Unix 样式的行尾。 更改文件行尾将更改 SHA-256 哈希。 若要避免此问题,请考虑使用
.gitattributes
将生成项目视为binary
文件。 - Web 服务器在提供文件内容的过程中对其进行修改。 例如,某些内容分发网络 (CDN) 会自动尝试缩小 HTML,从而对其进行修改。 可能需要禁用此类功能。
blazor.boot.json
文件无法正确加载或未正确缓存在客户端上。 常见原因包括以下任一种:- 自定义开发人员代码配置错误或出现故障。
- 一个或多个中间缓存层配置错误。
若要诊断哪些功能适用于你的情况,请执行执行操作:
- 通过读取错误消息来记下哪个文件触发错误。
- 打开浏览器的开发人员工具,然后在“网络”选项卡中查找。如有必要,请重新加载页面以查看请求和响应的列表。 在该列表中查找触发错误的文件。
- 检查响应中的 HTTP 状态代码。 如果服务器返回除“200 - 正常”(或其他 2xx 状态代码)以外的任何内容,则需要诊断服务器端问题。 例如,状态代码 403 表示存在授权问题,而状态代码 500 表示服务器以未指定的方式失败。 请参阅服务器端日志以诊断和修复应用。
- 如果资源的状态代码为“200 - 正常”,请在浏览器的开发人员工具中查看响应内容,并检查内容是否与预期的数据匹配。 例如,常见问题是错误配置了路由,因此请求甚至返回其他文件的
index.html
数据。 请确保对.wasm
请求的响应是 WebAssembly 二进制文件,对.dll
请求的响应是 .NET 程序集二进制文件。 如果不是,则需要诊断服务器端路由问题。 - 搜索以验证应用的已发布和已部署输出,并提供完整性 PowerShell 脚本故障排除。
如果确认服务器返回看似正确的数据,则必须在生成文件和传递文件之间修改内容。 若要对此进行调查,请执行以下操作:
- 如果在生成文件后修改文件,请检查生成工具链和部署机制。 例如,在 Git 转换文件行尾时,如前所述。
- 如设置为动态修改响应(例如,尝试缩小 HTML),请检查 Web 服务器或 CDN 配置。 Web 服务器可以实现 HTTP 压缩(例如,返回
content-encoding: br
或content-encoding: gzip
),因为这不会影响解压缩后的结果。 但是,Web 服务器不可以修改未压缩的数据。
完整性 PowerShell 脚本故障排除
使用 integrity.ps1
PowerShell 脚本来验证已发布和已部署的 Blazor 应用。 当应用出现 Blazor 框架无法识别的完整性问题时,该脚本将作为起点提供给 PowerShell Core 7 或更高版本。 应用可能需要自定义脚本,包括在 7.2.0 版之后的 PowerShell 版本上运行时。
此脚本将检查 publish
文件夹中的文件,并从部署的应用中下载这些文件,以检测包含完整性哈希的不同清单中的问题。 这些检查应检测最常见的问题:
- 你修改了已发布的输出中的文件,但未实现它。
- 应用未正确部署到部署目标,或者在部署目标的环境中发生了更改。
- 部署的应用与发布应用的输出之间存在差异。
在 PowerShell 命令行中使用以下命令调用脚本:
.\integrity.ps1 {BASE URL} {PUBLISH OUTPUT FOLDER}
在下面的示例中,脚本在位于 https://localhost:5001/
的本地运行的应用上执行:
.\integrity.ps1 https://localhost:5001/ C:\TestApps\BlazorSample\bin\Release\net6.0\publish\
占位符:
{BASE URL}
:已部署的应用的 URL。 尾部反斜杠 (/
) 是必需项。{PUBLISH OUTPUT FOLDER}
:应用的publish
文件夹的路径,或已发布的用于部署应用的位置。
注意
克隆 dotnet/AspNetCore.Docs
GitHub 存储库时,integrity.ps1
脚本可能会被 Bitdefender 或系统上存在的另一个病毒扫描程序隔离。 通常,该文件被病毒扫描程序的启发式扫描技术捕获,该技术只查找文件中可能指示存在恶意软件的模式。 若要防止病毒扫描程序隔离该文件,请在克隆存储库之前向病毒扫描程序添加一个例外。 以下示例是 Windows 系统上脚本的一个典型路径。 可以根据需要为其他系统调整路径。 {USER}
占位符是用户的路径段。
C:\Users\{USER}\Documents\GitHub\AspNetCore.Docs\aspnetcore\blazor\host-and-deploy\webassembly\_samples\integrity.ps1
警告:创建病毒扫描程序例外是危险操作,只有在你确定文件是安全的情况下才可以进行。
将文件的校验和与有效校验和值进行比较并不能保证文件的安全,但以维护校验和值的方式修改文件对于恶意用户来说并不简单。 因此,校验和作为一种常规安全方法很有用。 将本地 integrity.ps1
文件的校验和与以下值之一进行比较:
- SHA256:
32c24cb667d79a701135cb72f6bae490d81703323f61b8af2c7e5e5dc0f0c2bb
- MD5:
9cee7d7ec86ee809a329b5406fbf21a8
通过以下命令在 Windows OS 上获取文件的校验和。 为 {PATH AND FILE NAME}
占位符提供路径和文件名,并指明为 {SHA512|MD5}
占位符生成的校验和类型,可以是 SHA256
,也可以是 MD5
:
CertUtil -hashfile {PATH AND FILE NAME} {SHA256|MD5}
如果你有任何理由担心校验和验证在你的环境中不够安全,请咨询组织的安全领导以获得指导。
有关详细信息,请参阅 Microsoft Defender 防病毒的威胁防护概述。
禁用非 PWA 应用的资源缓存和完整性检查
在大多数情况下,不要禁用完整性检查。 禁用完整性检查并不能解决导致意外响应的根本问题,并且会导致丢失前面列出的权益。
在某些情况下,Web 服务器无法用于返回一致的响应,但别无选择,只能暂时禁用完整性检查,直到根本问题得到解决。
若要禁用完整性检查,请将以下内容添加到 Blazor WebAssembly 应用的项目文件 (.csproj
) 中的属性组:
<BlazorCacheBootResources>false</BlazorCacheBootResources>
BlazorCacheBootResources
还会根据 SHA-256 哈希禁用 Blazor 缓存 .dll
、.wasm
和其他文件的默认行为,因为属性指示无法依靠 SHA-256 哈希来确保正确性。 即使有此设置,浏览器的普通 HTTP 缓存仍可能会缓存这些文件,但是否发生这种情况取决于你的 Web 服务器配置和它所提供的 cache-control
标头。
注意
BlazorCacheBootResources
属性不会禁用渐进式 Web 应用程序 (PWA) 的完整性检查。 有关 PWA 的相关指南,请参阅禁用 PWA 的完整性检查部分。
我们无法提供需要禁用完整性检查的场景的详尽列表。 服务器可以在 Blazor 框架范围之外以任意方式应答请求。 该框架提供了 BlazorCacheBootResources
设置,使应用可以运行,但代价是不能保证应用可以提供的完整性。 同样,我们不建议禁用完整性检查,尤其是对于生产部署。 开发人员应设法解决导致完整性检查失败的根本完整性问题。
可能导致完整性问题的几个常见情况如下:
- 在 HTTP 上运行,无法检查完整性。
- 部署过程在发布后以任何方式修改了文件。
- 主机以任何方式修改了文件。
禁用 PWA 的资源缓存和完整性检查
Blazor 的渐进式 Web 应用程序 (PWA) 模板包含建议的 service-worker.published.js
文件,该文件负责获取和存储应用程序文件以供脱机使用。 这是普通应用启动机制的独立进程,具有其自己单独的完整性检查逻辑。
在 service-worker.published.js
文件中,出现以下行:
.map(asset => new Request(asset.url, { integrity: asset.hash }));
若要禁用完整性检查,请通过将该行更改为以下行来删除 integrity
参数:
.map(asset => new Request(asset.url));
同样,禁用完整性检查意味着会丢失完整性检查提供的安全保证。 例如,如果用户的浏览器在你部署新版本的那一刻缓存应用,则会存在风险,它可能会缓存旧部署中的某些文件和新部署中的某些文件。 如果发生这种情况,则在部署进一步更新之前,应用程序会在中断状态下停滞。