【发布时间】:2018-05-14 16:21:10
【问题描述】:
我正在使用 ASP.NET MVC(最新版本)。
假设有 2 页:
第 1 页:“输入数据”>> 第 2 页:“谢谢”
提交第 1 页后,您将被重定向到第 2 页。
我的目标:我想确保您在进入第 2 页后点击浏览器的后退按钮时不能返回第 1 页。相反,我希望你留在第 2 页上(或者每次按下后退按钮时都被推到第 2 页)。
我尝试过各种不同的东西。以下只是一些简化的伪代码...
[NoBrowserCache]
public ActionResult Page1(int userId)
{
var user = GetUserFromDb(userId);
if (user.HasAlreadySubmittedPage1InThePast)
{
// forward to page 2
return RedirectToAction("Page2", routeValues: new { userId = userId });
}
var model = new Page1Model();
return View("Page1", model);
}
[NoBrowserCache]
[HttpPost]
public ActionResult Page1(Page1Model model)
{
var user = GetUserFromDb(model.UserId);
if (user.HasAlreadySubmittedPage1InThePast)
{
// forward to page 2
return RedirectToAction("Page2", routeValues: new { userId = model.UserId });
}
// Save posted data to the db
// ...
return RedirectToAction("Page2", routeValues: new { userId = model.UserId });
}
public class NoBrowserCache : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
// Haha ... tried everything I found on the web here:
// Make sure the requested page is not put in the browser cache.
filterContext.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache);
filterContext.HttpContext.Response.Cache.SetNoStore();
filterContext.HttpContext.Response.Cache.AppendCacheExtension("no-cache");
filterContext.HttpContext.Response.Cache.SetExpires(DateTime.Now);
filterContext.HttpContext.Response.Expires = 0;
}
}
如果我能确保每次点击后退按钮都向服务器发送请求就好了。但是现在,单击后退按钮只会从浏览器的缓存中拉出第 1 页,而不会向服务器发送请求。所以目前,我没有机会通过服务器方式将您重定向到第 2 页。
有什么想法或建议吗?
谢谢各位!
顺便说一句:不涉及登录/身份验证。所以,我不能使用 Session.Abandon() 或类似的东西。如果可能的话,我宁愿使用一些基于服务器的代码而不是 javascript。
编辑 2017-5-12 在@ grek40 之后,我确保反chaching 语句最终出现在浏览器中。因此,我从上面的 C# 代码中完全删除了 [NoBrowserCache]-ActionFilterAttribute。相反,我在 _Layout.cshtml 的
部分添加了以下语句:<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Expires" content="0">
我确认这三行正在渲染到我的浏览器(使用浏览器的开发人员工具进行检查)。但是,缓存仍然有效。我仍然可以在没有任何服务器请求的情况下向后移动。使用 Google Chrome v62、Firefox Quantum v57 和 Microsoft Edge v41(均在 Win10 上)对此进行了测试。 #
编辑 2017-6-12 再次遵循@grek40 的建议:尝试过期:0 以及过期:-1。没有不同。我还是没能关掉浏览器的缓存。
【问题讨论】:
-
目前,让我们假设页面 1 完全缓存在客户端浏览器中,并且浏览器决定提供缓存页面而不进行任何类型的服务器查询。你出局了。您有责任处理客户端对服务器的请求,而不是控制客户端显示细节。所以基本上我假设第 1 页中有一些 Post-action 当用户发布两次时会出现问题。如果是这样,您必须防止重复发布(告诉用户他的输入由于之前的帖子而被忽略)而不是阻止前一页显示。
-
你的目标是什么?我认为它真的不是“不能回到第 1 页”,从伪代码中我猜它是“确保用户只能提交一次数据”。您需要采用“从不信任输入”原则并在提交时验证表单。您不能 100% 阻止从浏览器缓存中提供页面。
-
虽然您不能强制执行任何客户端行为,但您当然可以向浏览器提供一些提示,即您不希望客户端缓存。以下可能是相关的:stackoverflow.com/a/918346/5265292
-
各位,谢谢你们到目前为止的回复。 @grek40 和 Colin Young:我完全同意。当然,我正在所有重要步骤中进行服务器验证。所以,我不担心第二次回帖。这将导致您所建议的内容:“您已经提交了数据。”在我的应用程序的上下文中,目标是通过不让他回去让用户知道并感觉“没有办法回去”。他是否回去并不重要,但我宁愿让他留在第 2 页。
-
@grek40:对于您的第二篇文章(包括链接):这似乎正是我试图在代码示例中使用 ActionFilterAtrribute 实现的目标。虽然没有帮助。浏览器缓存仍然知道 Page-1。因此,无论我尝试了什么,最后后退按钮都会让我返回(无需触发服务器请求)。
标签: asp.net asp.net-mvc