Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel 4 CSRF on all POST requests

Tags:

php

csrf

laravel

Been looking into laravel lately, and trying to figure out the CSRF protection that they have. However, i can't get it work. Is there any way i can validate all post request submitted, with the CSRF filter? I've seen that the laravel system has:

    App::before(function($request)
{
    //
});

How would i be able to use this with the CSRF filter? Been trying a few different things like

App::before(function($request)
{
    Route::filter('csrf','post');
});

But i'm probably way off here.. how would this work? or is it even possible doing it this way?

like image 285
Dexty Avatar asked Jun 26 '13 20:06

Dexty


5 Answers

This is the best and the simplest solution:

Route::when('*', 'csrf', array('post'));

No need to group routes or to mess with constructors.

like image 126
Rafał Walczak Avatar answered Oct 21 '22 07:10

Rafał Walczak


You can use route groups. This will apply the specified options to any routes defined in a group:

Route::group(array('before' => 'csrf'), function()
{
    Route::post('/', function()
    {
    // Has CSRF Filter
    });

    Route::post('user/profile', function()
    {
    // Has CSRF Filter
    });

    Route::post(....);
});

For certain routes, or if grouping isn't what you want, you can also use a pattern filter:

//all routes beginning with admin, sent via a post http request will use the csrf filter
Route::when('admin/*', 'csrf', array('post'));

NOTE: this code would go in your routes.php file

like image 23
Blessing Avatar answered Oct 21 '22 08:10

Blessing


In my BaseController I have this:

public function __construct()
{
    $this->beforeFilter('csrf', array('on' => array('post', 'delete', 'put')));
    $this->beforeFilter('ajax', array('on' => array('delete', 'put')));
}

Having such App::before filter is an interesting approach but I don't know which is better?

like image 26
ux.engineer Avatar answered Oct 21 '22 06:10

ux.engineer


For some reason putting

$this->beforeFilter('csrf', array('on' => array('post', 'delete', 'put')));

into BaseController.php didn't work for me; I did the test with fake tokens. So i came with the following solution:

routes.php:

Route::group(array('before' => 'csrf'), function() {
    Route::resource('areas', 'AreaController');
    Route::resource('usuarios', 'UsuarioController');
    // ... more stuff
});

filters.php (csrf filter section):

Route::filter('csrf', function()
{
    if ($_SERVER['REQUEST_METHOD'] === 'POST' || $_SERVER['REQUEST_METHOD'] === 'PUT') {
        if (Session::token() != Input::get('_token'))
        {
            throw new Illuminate\Session\TokenMismatchException;
        }
    }
});

That did the trick for me.

like image 22
Nancho Avatar answered Oct 21 '22 08:10

Nancho


This will allow you to apply CSRF to all forms across all pages of your app

App::before(function($request)
{
    if ($request->getMethod() === 'POST') {
        Route::callRouteFilter('csrf', [], '', $request);
    }
});

Note: 'post' is the HTTP POST verb - so it will cover Laravel post, put, delete requests etc.

like image 41
Laurence Avatar answered Oct 21 '22 08:10

Laurence