【问题标题】:How to prevent users from going back to the previous page?如何防止用户返回上一页?
【发布时间】: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


【解决方案1】:

终于找到了解决办法。它基于 javascript,但非常简单。

我只需将以下 sn-p 添加到我的第 2 页(我不希望用户到达那里后就离开的页面):

<script type="text/javascript">

$(document).ready(function () {
    history.pushState({ page: 1 }, "title 1", "#nbb");
    window.onhashchange = function (event) {
        window.location.hash = "nbb";
    };
});

我在这里找到了这个:how to stop browser back button using javascript

感谢大家的支持。但“我自己的”解决方案是唯一有效的解决方案。

【讨论】:

  • 如果他们禁用了 Javascript 怎么办?这是一个问题吗?
  • @sab669:不,不是真正的问题。我非常清楚,我的解决方案在各个方面都不是安全的。仍然可以使用浏览器历史菜单返回。但这不是问题。我只是想防止明显的(浏览器后退按钮)。不过谢谢。
  • 虽然阻止用户导航通常被认为是不好的形式,但在“向导式”网站中通常是必要的。此解决方案在没有屏幕闪烁的情况下效果很好。
【解决方案2】:

这可以通过使用 javascript 来完成。使用以下代码

     <script type = "text/javascript" >
   function preventBack(){window.history.forward();}
    setTimeout("preventBack()", 0);
    window.onunload=function(){null};
   </script>

或检查以下link1link2

【讨论】:

  • 此答案中建议的链接对解决方案很有用,+1。
【解决方案3】:

这段小代码可能会帮助您解决问题。

<script type="text/javascript">
                /*To retain on the same view on Back Click*/
                history.pushState(null, null, window.location.href);
                window.addEventListener('popstate', function (event) {
                    history.pushState(null, null, window.location.href);
                    event.preventDefault();
                    });
</script>

【讨论】:

    【解决方案4】:

    您可以为客户端解决方案的每个页面添加一行 javascript:

    history.forward();

    请参阅文档on MDN。当有 一个页面要前进时(即当用户按下 BACK 按钮时),这将强制用户进入该页面。当用户已经在最近的页面时,什么都不做(没有错误)。

    【讨论】:

    • 也非常感谢您的建议。我以前试过这个(对不起,应该在我原来的帖子中提到这个 - 但我也试过很多其他的东西,我什至不记得了;))。无论如何,我再次尝试将此命令添加到我的第 1 页。在我第一次按下后退按钮时效果很好。短暂的闪烁表明我再次被推到第 2 页。但是当我第二次点击返回按钮时,它再次将我带回到第 1 页。所以,这真的不是一个选择:(
    【解决方案5】:
    Response.Cache.SetCacheability(HttpCacheability.NoCache);  // HTTP 1.1.
    Response.Cache.AppendCacheExtension("no-store, must-revalidate");
    Response.AppendHeader("Pragma", "no-cache"); // HTTP 1.0.
    Response.AppendHeader("Expires", "0"); // Proxies.
    

    【讨论】:

    • 感谢您提供此代码 sn-p,它可能会提供一些有限的即时帮助。一个正确的解释would greatly improve 其长期价值,通过展示为什么这是解决问题的好方法,并将使其对未来有其他类似问题的读者更有用。请edit您的回答添加一些解释,包括您所做的假设。
    • @Mike:谢谢你的代码 sn-p。但正如您可能在我的代码示例中看到的那样,我已经尝试过了(请参阅 [NoBrowserCache] 属性)。虽然没有帮助:(
    猜你喜欢
    • 2013-10-04
    • 2022-10-25
    • 1970-01-01
    • 1970-01-01
    • 2018-11-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多