DEBUG.WIKI
搬瓦工;先看线路,再选 VPS;CN2 GIA · 对应线路套餐;查看线路 →
野草云;香港 200Mbps 峰值;不限月流量 · BGP VPS;查看套餐 →
RackNerd;$21.99/年 · 1GB KVM

ASP.NET Core 10.0.9 后自定义输出缓存不再命中,检查响应阶段的认证判断

认证请求的自定义输出缓存突然失效,检查响应阶段 DefaultPolicy 是否再次清除 AllowCacheStorage。区分回移合入与正式运行时,保留 Cookie、身份和个性化数据的缓存限制。

升级到 ASP.NET Core 10.0.9 后,同一个 GET 接口每次都重新生成内容,没有异常,响应本身也正确;自定义 IOutputCachePolicy 明明已把 AllowCacheStorage 设为 true。如果这个策略原本允许已认证用户访问一份与身份无关的公共响应,要检查默认策略在响应阶段是否又关闭了存储。

这条回归在 10.0.9 到已核对的 10.0.12 中存在。普通匿名接口不一定受影响;默认就不允许认证响应缓存的应用,也不能把低命中率归到这里。

请求阶段允许,不代表最终会写入缓存

默认输出缓存只缓存符合条件的 GET/HEAD、200 响应,并排除认证请求与设置 Cookie 的响应。自定义策略在请求阶段覆盖默认决定,是扩展缓存规则的一种方式。

10.0.9 增加了响应阶段的认证检查:DefaultPolicy.ServeResponseAsync 发现用户已认证后,会再次把 AllowCacheStorage 清为 false。自定义策略若只在 CacheRequestAsync 中打开存储,在 ServeResponseAsync 中什么也不做,最后仍不会写入缓存。

因此,单独构造一个 AllowCacheStorage = true 的上下文测试自定义策略,可能完全通过,却覆盖不到实际中间件先调用默认策略的顺序。查看完整管线中的状态变化,尤其是默认策略执行后的值。

可以先记录实际服务的框架版本,而不是只看项目的目标框架:

dotnet --list-runtimes

这条命令查看当前环境安装的运行时。框架依赖部署还需核对应用实际选择的版本;自包含部署要查发布产物自身,服务器上另一份运行时不决定它的行为。

用不涉及用户数据的端点确认

在隔离环境选择一个明确与用户、租户和授权范围无关的测试响应,例如当前生成时间。保留与故障一致的认证、中间件顺序和命名缓存策略,连续请求同一个地址,检查返回体是否复用、服务端是否重复执行生成代码。Age 头可以作为辅助观察,不能单靠缺少这个头就断言无缓存。

对照时记录三个位置:请求阶段自定义策略结束、响应阶段默认策略结束、响应阶段自定义策略结束。若存储许可由 true 变成 false,且恰好发生在默认策略的已认证分支,才与这条回归吻合。

如果请求根本没进入指定策略、响应设置了 Cookie、状态码不是 200,或缓存键因查询字符串不断变化,应先处理这些实际差异。把 Cache-Control 响应头改成 public,也不会自动改掉输出缓存的策略状态。

不要只在响应阶段无条件设回 true

这样做能使某些样例恢复命中,却可能覆盖 Cookie、状态码、认证时机等其他禁止存储的决定。尤其是中间件之后才完成认证的请求,不能因为这个补丁被放进共享缓存。用户资料、租户数据和按权限裁剪的响应也不能套用公共缓存策略。

在无法安全证明响应与身份无关时,临时保持这条路径不缓存,并评估生成开销,是更可控的处理。不要为恢复命中率把默认安全条件全部移除,或退回缺少其他修正的旧运行时。

针对该问题的源码修正已经合入 release/10.0:请求阶段记录用户是否已经认证,响应阶段只额外拦住后来才变成已认证的请求,保留此前自定义策略的选择。分支合入不能当作正式运行时已经包含修复;采用维护版本前,需要核对该版本的发布内容和实际产物。

如果应用已有完整的自定义响应策略,确需临时调整,应重新计算自己的全部允许条件,保留状态码、Cookie、方法、身份与缓存键规则,并覆盖真实中间件顺序的集成检查。不要从一行 AllowCacheStorage = true 推导出一份完整策略。

完成更新后,同时验证符合条件的公共响应能够复用,个性化响应、设置 Cookie 的响应及晚于输出缓存完成认证的请求仍不被共享。恢复命中只能说明缓存路径工作,不能替代权限与隔离检查。