14

在网页中,我们提供了一个超链接 (GET),用户可以单击该超链接进行身份验证:

@Html.ActionLink("Please Login", "MyMethod", "MyController")

这映射到以下返回视图的控制器方法:

    [RequireHttps]
    public ActionResult MyMethod()
    {
        return this.View(new MyModel());
    }

此视图包含用户提供其凭据的表单;表单包含所需的 AntiForgeryToken。

当用户提交表单时,会调用以下 Controller 方法:

    [HttpPost]
    [RequireHttps]
    [ValidateAntiForgeryToken]
    public ActionResult MyMethod(MyModel model)
    {
        // my logic
    }

这工作得很好,大多数时候......

但是,如果用户让他们的浏览器在“相当长的”时间内保持打开状态,然后快速连续执行以下步骤:

  1. 单击超链接 (GET) 以加载登录表单
  2. 填写表格并提交

他们收到一个异常通知,通知他们 Anti-Forgery 令牌未提供或无效。

我不明白为什么会这样:视图(包含表单)是在浏览器休眠后创建的,因此防伪令牌应该都是“新鲜的”。但是,这种设计显然有问题,但我不确定如何最好地纠正它。

如果您有任何建议,请提前致谢。

格里夫

4

1 回答 1

16

我正在处理同样的问题,虽然我理解这个问题,但我不确定最佳解决方案。

Anti-ForgeryToken 进程将输入值放置在表单中,第二个值存储在 cookie RequestVerificationToken 中。这两个都提交到服务器,如果它们不匹配,则会引发错误。

RequestVerficationToken cookie 的过期值设置为 Session。因此,当用户让浏览器在页面上长时间打开然后提交时,cookie 的时间戳会与服务器上的会话超时值(默认为 20 分钟左右)进行比较,如果超过,则会将其删除因此令牌验证失败。

可能的解决方案,所有这些都有潜在的问题;

  1. 在页面上放置一个 javascript 计时器并以小于会话超时的某个值刷新。
  2. 在服务器上捕获 System.Web.Mvc.HttpAntiForgeryException - 并重定向到同一页面。
  3. 增加会话超时
  4. 更改防伪令牌的过期时间
于 2013-04-10T18:34:39.370 回答