14

Web ページで、ユーザーが認証のためにクリックできるハイパーリンク (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. フォームに入力して送信します

偽造防止トークンが提供されなかったか、無効であったことを通知する例外が発生します。

これが事実である理由がわかりません。ブラウザーが休止状態になった後にビュー (フォームを含む) が作成されるため、偽造防止トークンはすべて「新鮮」である必要があります。ただし、この設計には明らかに問題がありますが、それを修正する最善の方法がわかりません。

何か提案があれば、事前に感謝します。

グリフ

4

1 に答える 1

16

私はこれと同じ問題に取り組んでおり、問題を理解していますが、最善の解決策がまだわかりません。

Anti-ForgeryToken プロセスは、2 番目の値が Cookie RequestVerificationToken に格納されているフォームに入力値を配置します。これらは両方ともサーバーに送信され、一致しない場合はエラーがスローされます。

RequestVerficationToken Cookie の有効期限の値は、Session に設定されています。そのため、ユーザーがブラウザを開いたままページを長時間開いたまま送信すると、Cookie のタイム スタンプがサーバーのセッション タイムアウト値 (デフォルトでは 20 分程度) と比較され、超過した場合は削除されます。したがって、トークンの検証は失敗します。

考えられる解決策。すべてに潜在的な問題があります。

  1. ページに JavaScript タイマーを配置し、セッション タイムアウトよりも小さい値で更新します。
  2. サーバーで System.Web.Mvc.HttpAntiForgeryException をキャッチし、同じページにリダイレクトします。
  3. セッションのタイムアウトを増やす
  4. 偽造防止トークンの有効期限を変更する
于 2013-04-10T18:34:39.370 に答える