2015-09-18 20 views
8

私はログインアクションを保護したいAntiforgeryTokenアトリビュート - なぜ例外が発生しているのか知っていますが、それに対して良い解決策を見つけることはできません。MVC5 AntiForgeryToken - 提供された偽造防止トークンはユーザー ""のためのものでしたが、現在のユーザーは "xxx"です。例外?

レッツは、我々は次のような状況を持っていると言う:

  1. それは午前8時だ、アプリケーション・ユーザーが仕事に来ている、彼らが座って、ログインプロセスを開始 - 今、それは非常に可能性がことです一部のユーザーは同じValidationTokenを取得します。最初のログイン後、ログインしようとすると、上記の例外(またはその他のカスタム例外画面)が表示されます。これは、よりそうですが、それが起こることができる、と私はそれがないとき、ユーザーが例外を表示したくない -

  2. 一部のユーザーが誤って「バック」ボタンを押すと、再度ログインを試みた後、ログイン。

は、そこで問題は単純です - 上記の状況を防ぐ方法、またはユーザーが何もに気付かれないようにそれらを処理する方法。私は、次のことを試してみました:

  1. 真= AntiForgeryConfig.SuppressIdentityHeuristicChecksを設定します。 Global.asaxの内のApplication_Start - が問題を修正しなかったこと、私はまだ[OutputCache(NOSTORE = trueの場合、持続時間= 0、VaryByParam = "none" を)]の設定
  2. 同じ例外を取得再び、運が

今、私は手動でに考えていたが、アクション本体にトークンを検証していないエラーをキャッチし、チェック - [ValidateAntiForgeryToken]属性がと方法に試みは、匿名ユーザーによって行われた場合:

public ActionResult SomeAction() 
{ 
    try 
    { 
     AntiForgery.Validate(); 
    } 
    catch(HttpAntiForgeryException ex) 
    { 
     if(String.IsNullOrEmpty(HttpContext.User.Identity.Name)) 
     { 
      throw; 
     } 
    } 

    //Rest of action body here 
    //.. 
    //.. 
} 

は、上記のエラーを防止するようだ - をしかし、それは安全なのですか?代替手段はありますか?

ありがとうございます。

よろしくお願いいたします。

はEDIT:

最後の「ソリューション」は、ログインフォーム上のトークンの検証を無効にすることだった - 、それを処理するためのより良い方法があるかもしれませんが、私が見つけたすべてのソリューションは、鉱山に似醜い回避策が提案されたようです上記。

これらの選択肢がどれほど安全であるかを知る方法がないため(安全であれば)、ログイン時にトークン検証を無効にすることに決めました。

+0

スクリプトを使用して、ダブル送信を無効にすることができます。http://stackoverflow.com/questions/2830542/prevent-double-submission-of-forms-in-jquery –

+0

こんにちは、私はユーザーが戻るボタンを押すと同じ問題が発生していますブラウザで。あなたは何で終わりましたか? – VAAA

+0

@VAAA: は私の質問のEDITセクションを参照してください - 唯一のログインフォームが最後に、私たちはそこにトークンの検証を無効にして、私たちはこの問題を与えたことから。私たちはそれが単に問題の価値がないと率直に決めて、私は何も "クリーンな"解決策を見つけることができませんでした - ほんの少しの厄介な回避策(私はtry-catchで掲示しました)。 – user2384366

答えて

7

(グローバルで設定してください。CS):

AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.NameIdentifier; 

この

は、二重ログインの問題のために、第2の提出を停止するために提出し、元の日付と時刻を文書化するためのスクリプトを使用しようと、自分のトークンに名前識別子が追加されます同じトークンで

// jQuery plugin to prevent double submission of forms 
jQuery.fn.preventDoubleSubmission = function() { 
    $(this).on('submit',function(e){ 
    var $form = $(this); 

    if ($form.data('submitted') === true) { 
     // Previously submitted - don't submit again 
     e.preventDefault(); 
    } else { 
     // Mark it so that the next submit can be ignored 
     $form.data('submitted', true); 
    } 
    }); 

    // Keep chainability 
    return this; 
}; 

私たちは1つのことを知っています。バックボタンのようなユーザーはダブルクリックの習慣がありますが、これはAntiforgeryTokenの大きな問題です。

しかし、あなたのアプリケーションが何をするかによって、そのように強制する方法があります。最も簡単なのは、訪問者が自分の要求を「巻き戻す」必要があるように感じさせないようにすることです。

ユーザーが何が間違っているかを確認するには、フォームエラーメッセージが明確かつ簡潔であることを確認してください。文脈上の誤りはボーナスポイントを与える。

フォーム提出の間は常にフォームの状態を維持してください。 のパスワードやクレジットカード番号の他に、MVC フォームヘルパーには感謝の気持ちがありません。形態は、このようなエラーは、実際に フォームの送信に由来することがスマートであると コントローラレイアウトを表示又は形成する、角又はember.js等 SPAフレームワークで使用されるようなタブまたは隠しdiv要素に分散している場合@Html.LabelFor(x => x.FirstName)

エラーを表示するとき。 をホームコントローラまたは最初のタブに転送しないでください。

「何が起こっているの?」 - AntiForgeryTokenはあなたのウェブサイトがタイプSystem.Web.Mvc.HttpAntiForgeryExceptionの例外がスローされます検証しない場合は、ユーザーを維持するには、

を知らせました。

正しく設定した場合は、フレンドリーなエラーがオンになり、エラーページには例外が表示されず、何が起きているかを示す素晴らしいエラーページが表示されます。

少なくとも、HttpAntiForgeryExceptionをキャッチすることで、これらの例外をターゲットとするより有益なページをユーザーに提供することで、これを少し簡単にすることができます。

private void Application_Error(object sender, EventArgs e) 
{ 
    Exception ex = Server.GetLastError(); 

    if (ex is HttpAntiForgeryException) 
    { 
     Response.Clear(); 
     Server.ClearError(); //make sure you log the exception first 
     Response.Redirect("/error/antiforgery", true); 
    } 
} 

とあなたの/error/antiforgeryビューはは申し訳ありませんが、あなたが同じ情報を提出しようとしていることを伝えることができます二回もう一つのアイデアは、エラーを記録し、ログイン画面にユーザーを返すことです

OnExceptionメソッドをオーバーライドするHandleAntiforgeryTokenErrorAttributeクラスを作成します。

HandleAntiforgeryTokenErrorAttribute。CS:

public class HandleAntiforgeryTokenErrorAttribute : HandleErrorAttribute 
{ 
    public override void OnException(ExceptionContext filterContext) 
    { 
     filterContext.ExceptionHandled = true; 
     filterContext.Result = new RedirectToRouteResult(
      new RouteValueDictionary(new { action = "Login", controller = "Account" })); 
    } 
} 

グローバルフィルタ:

public class FilterConfig 
{ 
    public static void RegisterGlobalFilters(GlobalFilterCollection filters) 
    { 
     filters.Add(new HandleErrorAttribute()); 
     filters.Add(new HandleAntiforgeryTokenErrorAttribute() 
      { ExceptionType = typeof(HttpAntiForgeryException) } 
     ); 
    } 
} 

ログインが一般ロギング用アプリケーション

NLogの重要な部分であるとして、私はまた、すべての情報を記録するためにいくつかのツールを使用すると、重要なアプリケーション例外(Web例外を含む)に関する電子メール。

ElmahフィルタリングとWeb例外の電子メール。

編集: また、SafeFormというjQueryプラグインを参照してください。 Link

EDIT:

私はこの上の議論のアロット見ていると、対象のすべての人の意見は(owasp.orgからの引用)されてどのように私はそれを見て、有効なポイントを持っている

4クロスサイトリクエストフォージェリ(CSRF)は、彼らが が現在を認証しているているWebアプリケーション上で不要なアクションを実行するために、エンドユーザー を強制的に攻撃され、CSRF攻撃は、具体的な状態-変るをターゲットgの要求であり、データの盗難ではありません。偽造防止トークンは、「誰がログオンしているか」に特化した です。あなたが戻って、その後、ログインしたらそう、 古いトークンが有効ではなくなりました

ので、もし今、私はまた、ユーザーのIPアドレスを変更した場合に2ファクタ認証と私のアプリケーションで割り当てることのログインを許可するIPアドレスを使用しますクロスサイトリクエスト偽造が試されていた場合、ユーザーはIPアドレスと一致せず、2要素認可を要求します。セキュリティルーターが動作する方法とほとんど同じです。あなたのログインページにそれを残したいのであれば、友人のエラーページを設定しておけば、何か間違っていると見られるように人々は動揺しません。

+0

お返事ありがとうございました。遅れてご返事ありがとうございます。私はあなたのソリューションを少し変更します(私は隠れた入力フィールドを使用します: "提出された"値)。ブラウザの2つの異なるタブでログインフォームをシミュレートすることでシミュレートすることができます。両方のタブで「___RequestverificationToken」クッキーが同じであることがわかり、送信時に以前と同じエラーが発生します。私はこの例外をキャッチすることができますが、私はまだそれをどうしたらいいかわかりません... – user2384366

+0

真実この問題に対する本当の答えは、単純にログインフォームに偽造防止トークンを使用しないでください!ログインフォーム上のユーザーである「偽造」は意味がありません。ログインしていないユーザーは匿名ユーザーです。そのため、匿名ユーザーを使ってRequestverification Tokenを作成すると、ユーザーがログインした後にフォーム上に偽造トークンを使用する必要があります。同じブラウザとコンピュータ上のタブには違いはありません。 –

+1

正直言って、現時点ではちょっと混乱しています。例えば、ここに2つの異なる見解があるようです。 http://security.stackexchange.com/questions/2120/when-the -if-a-antiforgerytoken-is-not-needed-neededが必要です 私はログインフォームに反偽造トークンを使用するべきであるという例を挙げて非常に広範な答えを見つけました...他の多くの記事がありますそれ以外の場合は... 何も考えられない場合はもう一度お待ちしておりますが、何も入力されない場合は、ログイン時にトークンの検証を提案して無効にするようにします:) – user2384366

関連する問題