2014-03-24 11 views
18

Ich benutze Laravels CSRF-Schutz auf meiner öffentlichen Website. Da Laravel jedoch eine Sitzung verwendet, um dies zu verwalten, mache ich mir Sorgen, dass ein Benutzer möglicherweise von seinem Computer weggeht und zu einer Seite zurückkehrt, die er zuvor offen gelassen hat, nur um herauszufinden, dass Ajax-Anfragen nicht funktionieren. Die Ajax-Anfragen funktionieren nicht, weil die Sitzung abgelaufen ist (und das Token nicht mehr validiert wird). Wenn diese Benutzer angemeldete Benutzer wären, könnte ich sie einfach zurück zur Anmeldeseite umleiten. Da sie öffentliche Benutzer sind, muss der Benutzer die Seite aktualisieren, damit sie wieder funktioniert (peinlich).Wie erstellt und prüft Laravel ein CSRF-Token?

Oder liege ich falsch? Würde das CSRF-Token immer noch von Laravel validiert werden (selbst nachdem die Sitzung abgelaufen ist, sendet die Seite immer noch das Token ... aber was wird Laravel damit machen?). Eine optimale Lösung wäre, die Token teilweise basierend auf einem Zeitstempel zu haben, so dass wir die Token-Ablauflimits abgesehen von den Sitzungszeitgrenzen geben könnten. Ich könnte meine CSRF-Token für 2 Tage halten (also kehren nur die Benutzer, die 2 Tage weglaufen, zu einer toten Seite zurück).

Letztendlich bringt mich das auf meine Frage: Wo ist der spezifische Code im Laravel-Framework, der das behandelt? Ich versuche gerade, es zu lokalisieren. Gibt es auch einen einfachen Tropfen Ersatz, den ich machen kann, oder bin ich links, um meine eigene Version von csrf_token(); zu erstellen, um auf meinen Seiten auszugeben, und dann würde ich meinen eigenen Routenfilter erstellen müssen, um damit zu gehen.

Antwort

23

Laravel erleichtert dies nur für Sie, indem Sie den Token in der Sitzung gespeichert halten, aber der Code ist eigentlich Ihr (um zu ändern, wie Sie es wünschen). Werfen Sie einen Blick auf filters.php sollten Sie sehen:

Route::filter('csrf', function() 
{ 
    if (Session::token() != Input::get('_token')) 
    { 
     throw new Illuminate\Session\TokenMismatchException; 
    } 
}); 

Es sagt uns, dass, wenn Sie eine Route haben:

Route::post('myform', ['before' => 'csrf', 'uses' => '[email protected]']); 

Und die Benutzersitzung abläuft, wird es eine Ausnahme auslösen, aber man kann das tun arbeiten Sie sich, halten Sie Ihre eigenen Token gespeichert, wo immer Sie denken, ist besser, und stattdessen diese Ausnahme zu werfen, leiten Ihre Benutzer auf die Login-Seite:

Route::filter('csrf', function() 
{ 
    if (MySession::token() != MyCSRFToken::get()) 
    { 
     return Redirect::to('login'); 
    } 
}); 

und, ja, können Sie creat e your own csrf_token(), Sie müssen es nur vor Laravel laden. Wenn Sie in Laravel Quellcode an der helpers.php Datei betrachten, sehen Sie `ll, dass es nur diese Funktion erstellt, wenn es nicht bereits vorhanden ist:

if (! function_exists('csrf_token')) 
{ 
    function csrf_token() 
    { 
     ... 
    } 
} 
+1

Ah ... ich war dieser Codes bewusst, aber ich war auf der Suche tiefer in den Rahmen tatsächlich zu sehen versuchen, welche Berechnung getan wird. Aber Sie haben recht, wir können natürlich sehen, dass hier Sitzungen für CSRF verwendet werden. Das lässt mich denken, dass die typische Verwendung für CSRF-Schutz für eingeloggte Benutzer ist.Jedoch sende ich JSON in verschiedenen öffentlichen Bereichen meiner Website aus, die ich nicht leicht von anderen packen möchte, die versuchen könnten, die Site zu benutzen, als ob es eine öffentliche API wäre. – prograhammer

+0

Und ... Sie haben mir wirklich geholfen, indem Sie mich daran erinnert haben, dass wir diese Helfer außer Kraft setzen können. Also ist die sichere Wette für mich, das neu zu schreiben und diese Token aus der Sitzung zu holen. Danke nochmal Antonio! – prograhammer

4

Da dies eine beliebte Frage geworden ist, habe ich beschlossen, poste meine spezifische Lösung, die ganz schön funktioniert hat ...

Höchstwahrscheinlich wirst du eine header.php oder eine Teilansicht haben, die du oben auf all deinen Seiten verwendest, vergewissere dich, dass sie darin in der <head> enthalten ist Abschnitt:

<meta name="_token" content="<?=csrf_token(); ?>" /> 

In Ihrer filters.php:

Route::filter('csrf', function() 
{ 
    if (Request::ajax()) { 
     if(Session::token() != Request::header('X-CSRF-Token')){ 
      throw new Illuminate\Session\TokenMismatchException; 
     } 
    } 
}); 

Und in Ihrem routes.php

Route::group(array('before' => 'csrf'), function(){ 

    // All routes go in here, public and private 

}); 
+2

Fügen Sie einfach eine kleine Info hinzu, wenn Sie Ajax-Aufrufe verwenden, können Sie die folgende 'jQuery.ajaxSetup ({headers: {'X-CSRF-Token': $ ('meta [name = _token]'). Attr ("content")}}); '[source] (http://laravel.io/forum/04-03-2014-simple-ajax-post-response-in-laravel-4#reply-11226) –

+0

Yup. Das ist es, was ich in Laravel 5 mache. Es wird tatsächlich in den Laravel-Dokumenten erwähnt. :-) – prograhammer