2012-05-23 9 views
5

Ich bin interessiert an einem Schutz meiner Web-Anwendung mit der Generierung einer csrf-Token. Meine Frage ist, wie muss ich dieses Token zurück zu einem Server senden: mit Abfrageparameter oder HTTP-Header x-csrf-token?csrf token mit

Und was ist der Unterschied

Antwort

9

Da Sie Express verwenden, wird seine CSRF-Middleware (von Connect) verwenden können: http://www.senchalabs.org/connect/csrf.html

Sie können die kommentierten Quelle hier Kasse: https://github.com/senchalabs/connect/blob/master/lib/middleware/csrf.js

Alle Sie müssen diese Middleware einbeziehen und dann in Ihren POST-Formularen (oder PUT usw., welche Anfrage auch immer mutiert) die Variable _csrf auf den Wert req.session._csrf setzen.

prüfen Beispiel hier: https://github.com/senchalabs/connect/blob/master/examples/csrf.js

UPDATE

Da Connect 2.9.0 Sie req.csrfToken() statt req.session._csrf

Voll Beispiel verwenden müssen: https://github.com/senchalabs/connect/blob/master/examples/csrf.js

Commit: https://github.com/senchalabs/connect/commit/70973b24eb1abe13b2da4f45c1edbb78c611d250

UPDATE2

Die connect-Middleware in verschiedene Module (und die damit verbundenen repos) geteilt wurde, können Sie sie alle (einschließlich der CSRF ein) finden Sie hier: https://github.com/senchalabs/connect#middleware

+0

Ja, ich weiß, aber ich möchte wissen, was besser ist, zu verwenden: einen Header x-csrf-Token oder verstecktes Feld? – Erik

+0

Wie Sie hier sehen können: https://github.com/senchalabs/connect/blob/master/lib/middleware/csrf.js # L69 Express überprüft zunächst für den Wert POST, dann für den Wert Query-String und dann für die x-CSRF-Token-Header, so dass die besten ein verstecktes _csrf Feld mit dem Wert zu übergeben wäre. – alessioalex

+0

Ich möchte csrf-token auf ajax Anfragen verwenden, was soll ich dann verwenden? – Erik

3

Aus meiner Sicht sollten Sie Der POST-Parameter csrf beim Senden von Formularen in einem ausgeblendeten Feld. Dies ist der einzige Weg zu gehen.

Aber für AJAX-Anfragen würde ich Ihnen dringend empfehlen, stattdessen den X-CSRF-Token Header zu verwenden. Vor allem, wenn Sie es richtig gemacht haben, erspart es Ihnen, sich daran zu erinnern, das Token für jede POST-Anfrage hinzuzufügen. Wenn Sie Bibliotheken wie jQuery Form verwenden, kann das Hinzufügen zusätzlicher POST-Parameter zum Zeitpunkt des Sendens hackisch werden.

Wenn Sie beispielsweise jQuery für Ihre AJAX-Anfragen verwenden, können Sie a hook verwenden, um die X-CSRF-Token automatisch und transparent festzulegen, bevor die Anfrage gestellt wird. Daher ist sehr wenig clientseitige Code-Modifikation erforderlich. Und du sprengst die Großartigkeit deines Codes.

-

Eine beispielhafte Implementierung, die ich fast alle meine Projekte erfolgreich auf, bezogen auf Djangos ein, wäre:

jQuery(document).ajaxSend(function(event, xhr, settings) { 

    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 sameOrigin(url) { 
    // url could be relative or scheme relative or absolute 
    var host = document.location.host; // host + port 
    var protocol = document.location.protocol; 
    var sr_origin = '//' + host; 
    var origin = protocol + sr_origin; 
    // Allow absolute or scheme relative URLs to same origin 
    return (url == origin || url.slice(0, origin.length + 1) == origin + '/') || 
      (url == sr_origin || url.slice(0, sr_origin.length + 1) == sr_origin + '/') || 
      // or any other URL that isn't scheme relative or absolute i.e relative. 
      !(/^(\/\/|http:|https:).*/.test(url)); 
    } 

    function safeMethod(method) { 
    return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method)); 
    } 

    if (!safeMethod(settings.type) && sameOrigin(settings.url)) { 
    xhr.setRequestHeader("X-CSRFToken", getCookie('csrf.token')); 
    } 
}); 

Auf der Server-Seite, dann würden Sie nur Sie müssen einen Cookie mit dem CSRF-Token festlegen, damit der Client das Token problemlos abrufen kann. Ich ersetzte den app.use(express.csrf()) mit:

app.use((function(options) { 

    var csrf = express.csrf(options); 

    return function(req, res, next) { 

    function onCsrfCalled() { 
     var token = req.session._csrf; 
     var cookie = req.cookies['csrf.token']; 

     // Define a cookie if not present 
     if(token && cookie !== token) { 
     res.cookie('csrf.token', token); 
     } 

     // Define vary header 
     res.header('Vary', 'Cookie'); 

     next(); 
    } 

    csrf(req, res, onCsrfCalled); 
    } 
})());