I\'ve a payment system, where data is submitted to 3rd party site and than hauled back...
When data returns it hits specific url lets say /ok route. $_REQUEST[
The technique described by @jedrzej.kurylo works well for excluding one or two pages.
Here's a different technique if you need to exclude lots of pages from CSRF validation, with more future-proofing.
You can segment your routes, and apply different middleware to each. So you can put your payment routes into a separate route groups, and not apply VerifyCsrfToken to them. Here's how.
You'll notice in your routes
directory, you have the following tree:
routes/
routes/api.php
routes/web.php
Create a new file here, routes/payment.php
, and add your routes above to it:
<?php
use Illuminate\Support\Facades\Route;
Route::get('/payment/ok', 'TransactionsController@Ok');
Route::get('/payment/fail', 'TransactionsController@Fail');
In Laravel, Routes are processed by app\Providers\RouteServiceProvider.php
. You'll notice these functions: map()
and mapWebRoutes()
. Add to this file accordingly (I've excluded the stock comments for brevity).
public function map()
{
$this->mapApiRoutes();
$this->mapWebRoutes();
$this->mapPaymentRoutes(); // <---- add this line
}
protected function mapWebRoutes()
{
Route::middleware('web')
->namespace($this->namespace)
->group(base_path('routes/web.php'));
}
protected function mapPaymentRoutes() // <--- Add this method
{
Route::middleware('payment') // <--- this line is important
->namespace($this->namespace)
->group(base_path('routes/payment.php'));
}
Notice we've added a new middleware layer. This is important for the next step.
Your middleware for your route groups are defined in App\Http\Kernel.php
.
Update the $middlewareGroups
property, and add a middle entry for 'payment'. It can be exactly the same as web
, but without the VerifyCsrfToken
line.
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\Session\Middleware\AuthenticateSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
\App\Http\Middleware\NoClickjack::class,
\App\Http\Middleware\SecureReferrerPolicy::class,
\App\Http\Middleware\NoXssScripting::class,
],
// ********** Add this *******************
'payment' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\Session\Middleware\AuthenticateSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
// This is the line you want to comment-out / remove
// \App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
\App\Http\Middleware\NoClickjack::class,
\App\Http\Middleware\SecureReferrerPolicy::class,
\App\Http\Middleware\NoXssScripting::class,
],
'api' => [
'throttle:60,1',
'bindings',
],
];
Since version 5.1 Laravel's VerifyCsrfToken middleware allows to specify routes, that are excluded from CSRF validation. In order to achieve that, you need to add the routes to $except array in your App\Http\Middleware\VerifyCsrfToken.php class:
<?php namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as BaseVerifier;
class VerifyCsrfToken extends BaseVerifier
{
protected $except = [
'payment/*',
];
}
See the docs for more information.
Since Laravel 7.7 you can use method withoutMiddleware
eg:
Route::get('/payment/ok', 'TransactionsController@Ok')->withoutMiddleware(['csrf']);
Route::get('/payment/fail', 'TransactionsController@Fail')->withoutMiddleware(['csrf']);