Dexty
Dexty

Reputation: 1472

Laravel 4 CSRF on all POST requests

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?

Upvotes: 14

Views: 18060

Answers (7)

Victor
Victor

Reputation: 1041

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.

Upvotes: 0

Blessing
Blessing

Reputation: 4888

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

Upvotes: 23

Rafał Walczak
Rafał Walczak

Reputation: 543

This is the best and the simplest solution:

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

No need to group routes or to mess with constructors.

Upvotes: 30

Laurence
Laurence

Reputation: 60038

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.

Upvotes: 4

Nancho
Nancho

Reputation: 49

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.

Upvotes: 4

Rob W
Rob W

Reputation: 9142

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.

Upvotes: 0

ux.engineer
ux.engineer

Reputation: 11338

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?

Upvotes: 11

Related Questions