2014-07-11 6 views
1

jTable에서 MVC5 컨트롤러로 CRUD를 호출 할 때 AntiForgeryToken을 어떻게 전달합니까? 작업을 완료하려면 오히려 안전하지 않은 ValidateAntiForgeryToken 부분을 주석 처리해야합니다. 그렇지 않으면 "서버와 통신하는 동안 오류가 발생했습니다."라는 메시지가 나타납니다. 메시지.jTable에서 MVC5로 CRUD 항목을 수행 할 때 위조 토큰을 전달하는 방법은 무엇입니까?

JTable의 코드 :

$(document).ready(function() { 

    //Prepare jtable plugin 
    $('#CandidateTable').jtable({ 
     title: 'Candidates', 
     actions: { 
      listAction: '@Url.Action("List")', 
      deleteAction: '@Url.Action("Delete")', 
      updateAction: '@Url.Action("Edit")', 
      createAction: '@Url.Action("Create")' 
     }, 
     fields: { 
      ID: { 
       key: true, 
       create: false, 
       edit: false, 
       list: false 
      }, 
      FirstName: { 
       title: '@Html.DisplayNameFor(model => model.FirstName)', 
       width: '15%' 
      }, 
      MiddleName: { 
       title: '@Html.DisplayNameFor(model => model.MiddleName)', 
       width: '15%' 
      }, 
      LastName: { 
       title: '@Html.DisplayNameFor(model => model.LastName)', 
       width: '15%' 
      }, 
      AnonymousID: { 
       title: '@Html.DisplayNameFor(model => model.AnonymousID)', 
       width: '15%' 
      }, 
      Email: { 
       title: '@Html.DisplayNameFor(model => model.Email)', 
       width: '15%' 
      }, 
      GUID: { 
       title: '@Html.DisplayNameFor(model => model.GUID)', 
       width: '15%', 
       create: false, 
       edit: false 
      } 
     } 
    }); 

    //Load person list from server 
    $('#CandidateTable').jtable('load'); 
}); 

ASP.NET MVC 5 활동 만들기 :

[HttpPost] 
    [ValidateAntiForgeryToken] 
    public JsonResult Create([Bind(Include = "FirstName,MiddleName,LastName,AnonymousID,Email")] Candidate candidate) 
    { 
     try 
     { 
      if (ModelState.IsValid) 
      { 
       candidate.GUID = System.Guid.NewGuid(); 
       candidate.IsActive = true; 
       candidate.DateAdded = DateTime.Now.ToUniversalTime(); 
       candidate.DateModified = null; 
       db.Candidates.Add(candidate); 
       db.SaveChanges(); 

       return Json(new { Result = "OK", Record = candidate }); 
      } 
      else 
      { 
       throw new Exception("Form is not valid! Please correct it and try again."); 
      }     
     } 
     catch (Exception ex) 
     {     
      ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists see your system administrator."); 
      return Json(new { Result = "ERROR", Message = ex.Message }); 
     }    
    } 

UPDATE :

내가 그것을 알아 냈어. 임의의 필드 (AFT)를 추가하고 @ HTML.AntiForgeryToken 출력에 사용자 지정 입력을 추가해야했습니다. 삭제는

$('#CandidateTable').jtable({ 
     paging: true, 
     pageSize: 15, 
     sorting: true, 
     defaultSorting: 'LastName ASC', 
     title: 'Candidates', 
     actions: { 
      listAction: '@Url.Action("List")', 
      deleteAction: '@Url.Action("Delete")', 
      updateAction: '@Url.Action("Edit")', 
      createAction: '@Url.Action("Create")' 
     }, 
     fields: { 
      ID: { 
       key: true, 
       create: false, 
       edit: false, 
       list: false 
      }, 
      FirstName: { 
       title: '@Html.DisplayNameFor(model => model.FirstName)', 
       width: '15%' 
      }, 
      MiddleName: { 
       title: '@Html.DisplayNameFor(model => model.MiddleName)', 
       width: '15%' 
      }, 
      LastName: { 
       title: '@Html.DisplayNameFor(model => model.LastName)', 
       width: '15%' 
      }, 
      AnonymousID: { 
       title: '@Html.DisplayNameFor(model => model.AnonymousID)', 
       width: '15%' 
      }, 
      Email: { 
       title: '@Html.DisplayNameFor(model => model.Email)', 
       width: '15%' 
      },     
      __AFT__: { 
       create: true, 
       edit: true, 
       list: false, 
       input: function (data) { 
        return '@Html.AntiForgeryToken()'; 
       } 
      } 

     } 
+0

내가 사용하는 해결책은 대개 위조 방지 토큰의 값을 사용하여 요청에 사용자 지정 헤더를 추가 한 다음 서버에서 확인하는 것입니다. 그러나 jTable을 사용하여이를 수행하는 방법을 잘 모르겠습니다. AJAX 예제를 사용하여 몇 가지 지침을 원한다면 알려주십시오. –

+0

오, 아주 멋진 접근 방식. 내 방식은 조금 "해킹"을 느꼈다. 고맙습니다! – kcabrams

+0

@kcabrams : 대답을 업데이트로 추가하십시오. –

답변

0

우선은 안티 위조 토큰을 생성됩니다 View에 기능을 추가 할 수있는 기본 키 (ID)를 통과하기 때문에 이제 난 그냥 삭제에이 작업을 수행하는 방법을 알아낼 필요가있다 :

@functions{ 
    public string TokenHeaderValue() 
    { 
     string cookieToken, formToken; 
     AntiForgery.GetTokens(null, out cookieToken, out formToken); 
     return cookieToken + ":" + formToken;     
    } 
} 

@functions 블록은 당신이 당신의 Views에 기능을 추가 할 수 있습니다. 조직을 도와주는 한 곳에서 모든 기능을 유지하는 데 유용합니다.

그런 다음 자바 스크립트에서 당신은 AJAX 호출을 만들 것하고 RequestVerificationToken 헤더로 토큰을 추가

$.ajax("api/values", { 
    type: "post", 
    contentType: "application/json", 
    data: { }, // JSON data goes here 
    dataType: "json", 
    headers: { 
     'RequestVerificationToken': '@TokenHeaderValue()' //Can be named whatever 
    } 
}); 

지금 솔루션에 다음과 같은 유틸리티 메소드를 만듭니다

void ValidateRequestHeader(HttpRequestMessage request) 
{ 
    string cookieToken = ""; 
    string formToken = ""; 

    IEnumerable<string> tokenHeaders; 
    if (request.Headers.TryGetValues("RequestVerificationToken", out tokenHeaders)) 
    { 
     string[] tokens = tokenHeaders.First().Split(':'); 
     if (tokens.Length == 2) 
     { 
      cookieToken = tokens[0].Trim(); 
      formToken = tokens[1].Trim(); 
     } 
    } 
    AntiForgery.Validate(cookieToken, formToken); 
} 

및 통화 좋아해요 :

try{ 
    Utils.ValidateRequestHeader(request); 
} 
catch(HttpAntiForgeryException exc){ 
    //VALIDATION FAILED! RELEASE THE HOUNDS 
} 

ref : http://www.asp.net/web-api/overview/security/preventing-cross-site-request-forgery-(csrf)-attacks

+0

또 다른 훌륭한 솔루션입니다. 고마워. – kcabrams

0

이 코드가 주위에 놓여 있었지만 어쩌면 도움이 될지도 모릅니다. jtable은 $ .ajax를 사용하여 jtax가 요청한 것 같아서 작동해야한다고 생각합니다.

// Setup CSRF safety for AJAX: 
$.ajaxPrefilter(function(options, originalOptions, jqXHR) { 
    if (options.type.toUpperCase() === "POST") { 
     // We need to add the verificationToken to all POSTs 
     var token = $("input[name^=__RequestVerificationToken]").eq(0); 
     var headers = {}; 
     headers["__RequestVerificationToken"] = token.val(); 
     if (!token.length) return; 

     var tokenName = token.attr("name"); 

     // If the data is JSON, then we need to put the token in the QueryString: 
     if (options.contentType.indexOf('application/json') === 0) { 
      // Add the token to the URL, because we can't add it to the JSON data: 
      options.headers = headers; 
     } 
    } 
}); 
1

이 AntiForgeryToken을 추가하여 jTable의 동작을 삭제하는 방법을 찾았습니다. __AFT__을 생성 및 업데이트 작업에 올바르게 추가 했으므로 헤더를 추가하고 컨트롤러에서 가져올 필요가 없습니다. 작업을 삭제하기 위해 추가하려면 아래와 같이 사용자 정의 삭제를 작성할 수 있습니다. 코드 업데이트

var tokenId = '@Html.AntiForgeryToken()'; 

$('#CandidateTable').jtable({ 
    paging: true, 
    pageSize: 15, 
    sorting: true, 
    defaultSorting: 'LastName ASC', 
    title: 'Candidates', 
    actions: { 
     listAction: '@Url.Action("List")', 
     deleteAction: function (postData) { 
      postData.__RequestVerificationToken = $(tokenId).val(); 
      return $.Deferred(function ($dfd) { 
       $.ajax({ 
        url: '@Url.Action("Delete")', 
        type: 'POST', 
        dataType: 'json', 
        data: postData, 
        success: function (data) { 
         $dfd.resolve(data); 
        }, 
        error: function() { 
         $dfd.reject(); 
        } 
       }); 
      }); 
     }, 
     updateAction: '@Url.Action("Edit")', 
     createAction: '@Url.Action("Create")' 
    }, 
    fields: { 
     ID: { 
      key: true, 
      create: false, 
      edit: false, 
      list: false 
     }, 
     FirstName: { 
      title: '@Html.DisplayNameFor(model => model.FirstName)', 
      width: '15%' 
     }, 
     MiddleName: { 
      title: '@Html.DisplayNameFor(model => model.MiddleName)', 
      width: '15%' 
     }, 
     LastName: { 
      title: '@Html.DisplayNameFor(model => model.LastName)', 
      width: '15%' 
     }, 
     AnonymousID: { 
      title: '@Html.DisplayNameFor(model => model.AnonymousID)', 
      width: '15%' 
     }, 
     Email: { 
      title: '@Html.DisplayNameFor(model => model.Email)', 
      width: '15%' 
     },     
     __AFT__: { 
      create: true, 
      edit: true, 
      list: false, 
      input: function (data) { 
       return tokenId; 
      } 
     } 

    } 

본인 스스로 테스트하고 직접 시도했습니다. 희망이 도움이됩니다.