14
votes

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?

7
Check out the documention : four.laravel.com/docs/security you Will Find your anwser at the middle of the page :)Perry
FWIW, since this is still on the front page of Google, the most recent version of the security docs is: laravel.com/docs/securitydhazelett

7 Answers

30
votes

This is the best and the simplest solution:

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

No need to group routes or to mess with constructors.

23
votes

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

11
votes

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?

4
votes

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.

4
votes

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.

0
votes

The code you provided only creates the filter. You still need to use it in either your ROUTER or CONTROLLER (even in the basecontroller if need be).

In my opinion, using the filter in your ROUTES is the best place to use it.

0
votes

Simply add this to the BaseController.

// Be sure to call parent::__construct() when needed
public function __construct()
{
    // Perform CSRF check on all post/put/patch/delete requests
    $this->beforeFilter('csrf', array('on' => array('post', 'put', 'patch', 'delete')));
}

This add the CSRF filter to all post, put, patch and delete request.