ASP.NET Core 2.1:在 HTTP POST 验证失败后导航回页面显示浏览器错误

Posted

技术标签:

【中文标题】ASP.NET Core 2.1:在 HTTP POST 验证失败后导航回页面显示浏览器错误【英文标题】:ASP.NET Core 2.1: Navigating back to a page after an HTTP POST fails validation displays a browser error 【发布时间】:2018-07-12 17:50:07 【问题描述】:

问题:

使用 ASP.NET Core 2.1 MVC 项目,我在使用浏览器后退按钮返回表单后收到以下浏览器错误消息,其中表单 POST 未通过服务器端验证:

Firefox 中的错误消息:

文档已过期

此文档不再可用。

请求的文档在 Firefox 的缓存中不可用。

作为安全预防措施,Firefox 不会自动重新请求敏感文档。 单击重试以从网站重新请求文档。

Chrome 中的错误消息:

确认重新提交表单

此网页需要您之前输入的数据才能 正确显示。您可以再次发送此数据,但这样做您 将重复此页面之前执行的所有操作。

按重新加载按钮重新提交加载页面所需的数据。

ERR_CACHE_MISS

重现步骤:

    提交 html 表单帖子,其中服务器端验证失败 导航到不同的 URL 点击浏览器返回按钮,返回表单页面

注意事项:

这似乎与 Antiforgery 系统禁用响应缓存 (https://docs.microsoft.com/en-us/aspnet/core/performance/caching/middleware?view=aspnetcore-2.1) 有关。

Antiforgery 系统用于生成安全令牌以防止 跨站点请求伪造 (CSRF) 攻击设置 Cache-Control 和 Pragma 标头为 no-cache 以便不缓存响应。为了 有关如何禁用 HTML 表单的防伪令牌的信息 元素,请参阅 ASP.NET Core 防伪配置。

我可以确认的是,如果您从 HTML 表单中删除 @Html.AntiForgeryToken(),浏览器错误消息就会消失。

这在 ASP.NET MVC5 中使用 AntiForgeryToken 不是问题。

问题:

ASP.NET Core 2.1中,有没有人找到办法继续使用Antiforgery系统,并防止在使用浏览器返回按钮时显示此浏览器错误消息?

这是我的 POST 操作:

    [HttpPost]
    [ValidateAntiForgeryToken]
    [ActionName("Contact-Form")]
    public async Task<ActionResult> ContactForm(ContactFormViewModel cfvm)
    
        if (ModelState.IsValid)
        
            // << Handling of the form submit code here >>

            TempData["Success"] = string.Format("Your contact request was submitted successfully!");

            return RedirectToAction("Contact-Form-Success");
        

        TempData["Error"] = "The form did not submit successfully. Please verify that all of the required fields are filled.";
        return View();
    

更新:

我在 ASP.NET Core Docs 上发布了这个问题: https://github.com/aspnet/Docs/issues/7590

【问题讨论】:

“在使用 AntiForgeryToken 的 ASP.NET MVC5 中不是问题”,“有没有人找到继续使用 Antiforgery 系统并防止出现此浏览器错误消息的方法” 那么是哪一个?你的意思是这不是框架的问题,还是你的问题不是由防伪引起的 Antiforgery 并未在 ASP.NET MVC5 中引起此问题,但它现在在 ASP.NET Core 2.1 中引起了问题。我正在将 MVC5 项目迁移到 Core 2.1,这就是我提到旧框架的原因。 我认为当您单击后退按钮时,他说这是 .Net Core 中的一个新问题,尽管我认为出于安全原因出现错误是有道理的,以防他们重新提交表单或干预 ViewState页面..您只需要使用自定义错误页面以礼貌的方式呈现它。 @numbtongue 在没有自定义错误页面的情况下,其他网站如何避免这种情况?我没有看到任何主要网站有这个问题。例如,如果您向 ASP.NET (login.asp.net/account/login) 提交无效登录,然后转到其他页面,然后返回浏览器,则不会在此处显示浏览器错误消息。 如果它是一个单页网站,他们可以管理浏览器历史记录,这样您就不会真正离开该页面,但好问题可能有人可以回答.. 【参考方案1】:

这不是特定于语言的问题。这是一种浏览器行为。说这不是 ASP.NET MVC 5 的问题是不正确的。

解决方案: 解决此问题的常用方法是 PRG pattern,它自 1995 年以来一直存在。

可以在here找到一个使用TempData的ASP.NET Core实现

我认为这个link 对您最有帮助,因为它演示了在 MVC 5 和 MVC 6 中实现的方法。

我希望这会有所帮助!

如果时间允许,我将尝试使用基于剃须刀页面启动项目的示例尽快更新这篇文章。

【讨论】:

我的问题不在于模型状态和“确认表单重新提交”弹出窗口。我遇到的浏览器错误是不同的,我相信是由于 Antiforgery 令牌没有被缓存。您的 PRG 答案可能会避免发生此浏览器错误(因为它正在执行新的 GET),但它并没有解决根本问题。如果您可以在 MVC5 中重现浏览器缓存错误,请告诉我,但我只是在升级到 Core 2.1 后才遇到它。 很公平。 ^^ 不应缓存防伪令牌。新的提交应该需要一个新的令牌。错误正是您应该看到的。按照这个答案的建议遵循 PRG 模式。 感谢@ChrisPratt 澄清防伪令牌。它让我失望,因为它们曾经被缓存在 MVC5 中。抱歉@AdamVincent 质疑您的答案。将其标记为正确。那么,您链接的关于使用 ModelState 帮助程序实现 TempData 的 ASP.NET Core 1.0 文章,您在 Core 2.1 中仍会使用吗? @Wellspring 我相信质疑一切!我零冒犯。我看了一下这篇文章,并自己实现了它。我承认,我不喜欢这个解决方案,但它是迄今为止我能找到的最深思熟虑的解决方案。我会支持你在 github.com 上打开的问题。我认为 asp.net 核心团队可以提高开发者的生活质量,这种模式已经存在了很长时间。

以上是关于ASP.NET Core 2.1:在 HTTP POST 验证失败后导航回页面显示浏览器错误的主要内容,如果未能解决你的问题,请参考以下文章

AWS负载均衡器后面的ASP.NET Core 2.1 HTTPS重定向?

asp.net core 2.1,Include() 函数不适用于 db first 方法

有没有办法在 ASP.NET Core 2.1 中捕获对 Razor 页面不存在的自定义处理程序的 HTTP 请求?

小5聊Asp.Net Core 2.1 主要依赖那些dll和版本

ASP.NET Core 2.1 MVC - 无法设置从 Web api 响应接收到的 cookie

ASP.Net Core 2.1 API JWT 无 cookie 会话?