2012-09-09 8 views
10

私は@Html.AntiForgeryToken()で深刻な問題に直面しています。私は、新しいメンバーを作成/登録するビューを作成した登録コントローラーを持っています。その理由のために、私は@Html.AntiForgeryToken()を私の主な送信フォームにSALTを使わずに使った。今私は、ユーザー名のテキストボックスのぼかしイベントのデータベース上に既に存在する場合は、ユーザー名を検証したいと思います。この検証のために、私は「検証」という名前の新しいコントローラを書いて、一定の検証SALTと方法を書いた:複数の@Html.AntiForgeryToken()を1つのページで2つの異なる形式で使用することは可能ですか?

[HttpPost] 
    [ValidateAntiForgeryToken(Salt = @ApplicationEnvironment.SALT)] 
    public ActionResult username(string log) { 
     try { 
      if (log == null || log.Length < 3) 
       return Json(log, JsonRequestBehavior.AllowGet); 

      var member = Membership.GetUser(log); 

      if (member == null) { 
       //string userPattern = @"^([a-zA-Z])[a-zA-Z_-]*[\w_-]*[\S]$|^([a-zA-Z])[0-9_-]*[\S]$|^[a-zA-Z]*[\S]$"; 
       string userPattern = "[A-Za-z][A-Za-z0-9._]{3,80}"; 
       if (Regex.IsMatch(log, userPattern)) 
        return Json(log, JsonRequestBehavior.AllowGet); 
      } 

     } catch (Exception ex) { 
      CustomErrorHandling.HandleErrorByEmail(ex, "Validate LogName()"); 
      return Json(log, JsonRequestBehavior.AllowGet); 
     } 
     //found e false 
     return Json(log, JsonRequestBehavior.AllowGet); 

    } 

メソッドが正常に動作しています。私は[ValidateAntiForgeryToken]なしでHTTP Getアノテーションをチェックして、期待通りの結果を得ました。

私はグーグルで、与えられたソリューションの多くをチェックしましたが、これらのどれも動作していません。私の検証コントローラでは、同じページに別のフォームを使用し、偽造トークンでSALTを使用しました。

:メイン提出フォームの まず偽造防止トークン:

@using(Html.BeginForm( "作成"、 "登録")){ Html.AntiForgeryToken @() @ Html.ValidationSummary(真)...}

セカンド偽造防止トークン:

<form id="__AjaxAntiForgeryForm" action="#" method="post"> 
    @Html.AntiForgeryToken(SALT) 
</form> 

とJavaScriptで私はこの得た私の私の放火犯でこの

<script type="text/javascript" defer="defer"> 
    $(function() { 
     AddAntiForgeryToken = function (data) { 
      data.__RequestVerificationToken = $('#__AjaxAntiForgeryForm input[name=__RequestVerificationToken]').val(); 
      return data; 
     }; 

     if ($("#LogName").length > 0) { 

      $("#LogName").blur(function() { 
       var user = $("#LogName").val(); 
       var logValidate = "/Validation/username/"; 
       //var URL = logValidate + user; 
       //var token = $('#validation input[name=__RequestVerificationToken]').val(); 
       data = AddAntiForgeryToken({ log: user }); 

       $.ajax({ 
        type: "POST", 
        dataType: "JSON", 
        url: logValidate, 
        data: data, 
        success: function (response) { 
         alert(response); 
        } 
       }); 

      }); 

     } 
    }); 
</script> 

使用:渡されたが、私は1パッシングとは異なるクッキーを得たクッキーのセクションで

log=admin&__RequestVerificationToken=NO8Kds6B2e8bexBjesKlwkSexamsruZc4HeTnFOlYL4Iu6ia%2FyH7qBJcgHusekA50D7TVvYj%2FqB4eZp4VDFlfA6GN5gRz7PB%2ByZ0AxtxW4nT0E%2FvmYwn7Fvo4GzS2ZAhsGLyQC098dfIJaWCSiPcc%2FfD00FqKxjvnqmxhXvnEx2Ye83LbfqA%2F4XTBX8getBeodwUQNkcNi6ZtAJQZ79ySg%3D%3D 

を: 実際のクッキーを:

ws5Dt2if6Hsah rW2nDly P3cW1smIdp1Vau 0TXOK1w0ctr0BCso/nbYu w9blq/QcrXxQLDLAlKBC3Tyhp5ECtK MxF4hhPpzoeByjROUG0NDJfCAlqVVwV5W6lw9ZFp/VBcQmwBCzBM/36UTBWmWn6pMM2bqnyoqXOK4aUZ4= 

これは、1ページに2つの偽造防止トークンを使用したためだと思います。しかし、私の考えでは、最初に発生したものが生成され、次は検証を確認する必要があるため、2を使用するべきです。しかし、これは私の推測であり、私は間違っていると思うので、私はあなたからの助けが必要です。

誰も私が2つの偽造防止法または1つを使用するべきであるという事実を説明できますか?

答えて

8

苦労の最後の8時間は私にソリューションを提供します....事前にすべてのいただきありがとうございます。

まず最初に、はい、ページ内に2つの偽造防止トークンを使用することに害はありません。そして2番目に、クッキーと提供トークンを一致させる必要はありません。トークンの提供は常に異なり、サーバーで検証されます。我々は[HttpGet]動詞を使用する場合は偽造防止の検証プロセスにトークンを要求からRequest.Form['__RequestVerificationToken']値を取得することによって検証されているので

偽造防止トークンは..動作しません。REF:Steven Sanderson's blog: prevent cross...

ソリューション

マイ修正コントローラ:

[HttpPost] 

     [ValidateAntiForgeryToken(Salt = @ApplicationEnvironment.SALT)] 
//change the map route values to accept this parameters. 
     public ActionResult username(string id, string __RequestVerificationToken) { 
     string returnParam = __RequestVerificationToken; 

     try { 
      if (id == null || id.Length < 3) 
       return Json(returnParam, JsonRequestBehavior.AllowGet); 

      var member = Membership.GetUser(id); 

      if (member == null) { 
       //string userPattern = @"^([a-zA-Z])[a-zA-Z_-]*[\w_-]*[\S]$|^([a-zA-Z])[0-9_-]*[\S]$|^[a-zA-Z]*[\S]$"; 
       string userPattern = "[A-Za-z][A-Za-z0-9._]{3,80}"; 
       if (Regex.IsMatch(id, userPattern)) 
        return Json(returnParam, JsonRequestBehavior.AllowGet); 
      } 

     } catch (Exception ex) { 
      CustomErrorHandling.HandleErrorByEmail(ex, "Validate LogName()"); 
      return Json(returnParam, JsonRequestBehavior.AllowGet); 
     } 
     //found e false 
     return Json(returnParam, JsonRequestBehavior.AllowGet); 
    } 

同じページ内の私の最初のフォーム:

@using (Html.BeginForm("Create", "Register")) { 

    @Html.AntiForgeryToken(ApplicationEnvironment.SALT) 

    @Html.ValidationSummary(true) 
    .... 
} 

同じページ内の私の第二の形式:

**<form id="validation"> 
    <!-- there is harm in using 2 anti-forgery tokens in one page--> 
    @Html.AntiForgeryToken(ApplicationEnvironment.SALT) 
    <input type="hidden" name="id" id="id" value="" /> 
</form>** 

この問題を解決するためのjQuery:

$("#LogName").blur(function() { 
      var user = $("#LogName").val(); 
      var logValidate = "/Validation/username/"; 
      $("#validation #id").val(user); 
      **var form = $("#validation").serialize(); // a form is very important to verify anti-forgery token and data must be send in a form.** 

      var token = $('input[name=__RequestVerificationToken]').val(); 

      $.ajax({ 
       **type: "POST", //method must be POST to validate anti-forgery token or else it won't work.** 
       dataType: "JSON", 
       url: logValidate, 
       data: form, 
       success: function (response) { 
        alert(response); 
       } 
      }); 
     }); 
関連する問題