2016-09-01 85 views
2

我正在使用用於CSRF保護的express中間件csurf。如果我將它與表單一起使用,將令牌放入隱藏字段中,路由後面的操作就可以工作。現在我想做一個簡單的AJAX調用,但是csurf說它是無效的。csurf AJAX調用 - 無效的CSRF令牌

AJAX調用:

$('.remove').on('click', function() { 
    var csrf = $(this).attr('data-csrf'); 
    $.ajax({ 
     type: 'DELETE', 
     url: '/user/' + $(this).attr('data-id'), 
     data: { 
      _csrf: csrf 
     }, 
     success: function (data) { 
      //..... 
     } 
    }); 
}); 

並在視圖的一部分:

<td class="uk-table-middle"> 
    <button data-id="{{ _id }}" data-csrf="{{ csrfToken }}" class="uk-button-link uk-text-large remove"> 
     <i class="uk-icon-remove"></i> 
    </button> 
</td> 

而且從中間件初始化:

import * as csurf from 'csurf'; 
// init bodyparse and and and... 
app.use(csurf()); 

回答

0

我不知道中表示,但通常情況下,CSRF令牌位於cookie內,因此您需要這兩個功能:

function getCookie(name) { 
    var cookieValue = null; 
    if (document.cookie && document.cookie != '') { 
     var cookies = document.cookie.split(';'); 
     for (var i = 0; i < cookies.length; i++) { 
      var cookie = jQuery.trim(cookies[i]); 
      // Does this cookie string begin with the name we want? 
      if (cookie.substring(0, name.length + 1) == (name + '=')) { 
       cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); 
       break; 
      } 
     } 
    } 
    return cookieValue; 
} 

function csrfSafeMethod(method) { 
    // these HTTP methods do not require CSRF protection 
    return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method)); 
} 

然後:

var csrftoken = getCookie('csrftoken'); 
$.ajax({ 
    url : formURL, 
    type: "POST", 
    data : postData, 
    beforeSend: function(xhr, settings){ 
     if (!csrfSafeMethod(settings.type)) xhr.setRequestHeader("X-CSRFToken", csrftoken); 
    }, 
    success:function(data, textStatus, jqXHR){ 

    }, 
    error: function(jqXHR, textStatus, errorThrown){ 
        //if fails 
    } 
}); 

或者,如果你不想使用jQuery,您可以使用XMLHttpRequest使AJAX請求:

var csrftoken = getCookie('csrftoken'); 
var xhr = new XMLHttpRequest(); 

xhr.open('POST', url); 
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); 
xhr.setRequestHeader("X-CSRFToken", csrftoken); 
xhr.onload = function(){ 
    if(xhr.status === 200){ 
     var response = JSON.parse(xhr.responseText); 
     console.log(response) 
    } 
}; 
xhr.send(encodeURI('category=' + cat)); 
+0

這並沒有幫助我。它不工作的原因是,我發送給模板一個數組和令牌。並且在模板中遍歷數組,並且在此範圍內未找到令牌....不知道._。 – R3Tech

0

的唯一原因這種方法不起作用的是,你沒有通過你的ajax請求傳遞cookie。當我查看代碼時,我正在努力解決這個問題。

Csurf需要您傳遞存儲在Cookie上的密鑰(_csrf)。餅乾必須通過基於域的權限的限制(除非你的服務器允許CORS)

在我的情況下,我用fetch向過往與同域請求餅乾(我沒有允許CORS)

const { _csrf, someData } = jsonData; // _csrf here you got from the form 
const response = await fetch("/api/some/endpoint", { 
    method: "POST", 
    credentials: "same-origin", // here is the option to include cookies on this request 
    headers: { 
    "x-csrf-token": _csrf, 
    "Content-Type": "application/json" 
    }, 
    body: JSON.stringify({ someData }) 
}); 

請注意上面的代碼我使用es6格式。你可以改變same-origininclude如果您如果使用jQuery作爲庫請求給不同的域a.k.a CORS see the doc here

,這個代碼可以對你有用。這段代碼沒有經過測試,你應該根據你使用的庫找出你自己。

$.ajax({ 
    url: 'http://your.domain.com/api/some/endpoint', 
    xhrFields: { withCredentials: true }, // this include cookies 
    headers: {'x-csrf-token': 'YourCSRFKey'} 
}) 

請自由地就後數據傳遞_csrf值時,查詢字符串使用自己的名字。在我上面的示例中,我使用名稱爲x-csrf-token的標頭,但您可以使用其他基於以下屏幕截圖代碼的方法。

Sample code from csurf when geting _csrf value