2015-09-25 107 views
5

所以我想POST fileUpload以及AntiForgeryToken通過AJAX。這裏是我的代碼:如何通過jquery ajax發送AntiForgeryToken(CSRF)以及FormData

查看

@using (Html.BeginForm("Upload", "RX", FormMethod.Post, new {id = "frmRXUpload", enctype = "multipart/form-data"})) 
{ 
    @Html.AntiForgeryToken() 
    @Html.TextBoxFor(m => m.RXFile, new {.type = "file"}) 
    ...rest of code here 
} 

<script> 
    $(document).ready(function(){ 
     $('#btnRXUpload').click(function() { 
      var form = $('#frmRXUpload') 

      if (form.valid()) { 
       var formData = new FormData(form); 
       formData.append('files', $('#frmRXUpload input[type="file"]')[0].files[0]); 
       formData.append('__RequestVerificationToken', fnGetToken()); 

       $.ajax({ 
        type: 'POST', 
        url: '/RX/Upload', 
        data: formData, 
        contentType: false, 
        processData: false 
       }) 
      } 
     }) 
    }) 
</script> 

控制器

[HttpPost] 
[ValidateAntiForgeryToken] 
public ActionResult Upload() 
{ 
    //rest of code here 
} 

我得到

的防僞標記無法解密。如果此應用程序由Web場或羣集託管

錯誤通過提琴手。任何想法如何解決這個問題?

我找到了答案:

<script> 
     $(document).ready(function(){ 
      $('#btnRXUpload').click(function() { 
       var form = $('#frmRXUpload') 

       if (form.valid()) { 
        var formData = new FormData(form.get(0)); //add .get(0) 
        formData.append('files', $('#frmRXUpload input[type="file"]')[0].files[0]); 

        $.ajax({ 
         type: 'POST', 
         url: '/RX/Upload', 
         data: formData, 
         contentType: false, 
         processData: false 
        }) 
       } 
      }) 
     }) 
    </script> 
+0

什麼是'fnGetToken()'? –

+0

如果應用程序未託管在Web場或羣集上,此行爲是否會更改?非Ajax請求是否工作? –

+0

@StephenMuecke:獲取標記字符串的函數 – warheat1990

回答

4

終於找到了答案:

我只需要在表單中添加.get(0),下面的代碼:

<script> 
     $(document).ready(function(){ 
      $('#btnRXUpload').click(function() { 
       var form = $('#frmRXUpload') 

       if (form.valid()) { 
        var formData = new FormData(form.get(0)); //add .get(0) 
        formData.append('files', $('#frmRXUpload input[type="file"]')[0].files[0]); 
        //formData.append('__RequestVerificationToken', fnGetToken()); //remark this line 

        $.ajax({ 
         type: 'POST', 
         url: '/RX/Upload', 
         data: formData, 
         contentType: false, 
         processData: false 
        }) 
       } 
      }) 
     }) 
    </script> 
+0

$(form).get(0)也幫助我越過了界限。 Thanx mate !!! – Arjmand

3

您需要將令牌添加到請求頭,而不是形式。就像這樣:

 if (form.valid()) { 
      var formData = new FormData(form); 
      formData.append('files', $('#frmRXUpload input[type="file"]')[0].files[0]); 

      $.ajax({ 
       type: 'POST', 
       url: '/RX/Upload', 
       data: formData, 
       contentType: 'multipart/form-data', 
       processData: false, 
       headers: { 
        '__RequestVerificationToken': fnGetToken() 
       } 
      }) 
     } 

編輯 我是如何解決這個問題,我自己回想起來,我記得標準ValidateAntiForgeryTokenAttribute看起來這並不總是得到填充一個AJAX請求的Request.Form對象。 (就你而言,文件上傳需要multipart/form-data內容類型,而CSRF令牌的表單發佈需要application/x-www-form-urlencoded。您設置了contentType=false,但這兩個操作需要衝突的內容類型,這可能是您問題的一部分)。因此,爲了驗證服務器上的令牌,你需要寫你的操作方法爲先檢查請求頭中的令牌自定義屬性:

public sealed class ValidateJsonAntiForgeryTokenAttribute 
          : FilterAttribute, IAuthorizationFilter 
{ 
    public void OnAuthorization(AuthorizationContext filterContext) 
    { 
     if (filterContext == null) 
     { 
      throw new ArgumentNullException("filterContext"); 
     } 

     var httpContext = filterContext.HttpContext; 
     var cookie = httpContext.Request.Cookies[AntiForgeryConfig.CookieName]; 
     AntiForgery.Validate(cookie != null ? cookie.Value : null, 
          httpContext.Request.Headers["__RequestVerificationToken"]); 
    } 
} 

更多信息(有點過時了)here

+0

該標記可以添加到FormData中。如果OP的當前代碼不起作用,那麼這也不會。 –

+0

終於找到答案,查看我更新的帖子。 – warheat1990