在laravel中禁用特定路由的csrf

时间:2015-07-30 16:36:33

标签: php laravel laravel-5 laravel-5.1

我有一个支付系统,数据提交给第三方网站,然后拖回来......

当数据返回时,它会命中特定的url让我们说/ ok route。 $_REQUEST['transaction']

但由于laravel中间件我得到令牌不匹配。第三方支付API无法生成令牌,所以我如何禁用它?只为这条路线?

还是有更好的选择?

Route::get('/payment/ok',   'TransactionsController@Ok');
Route::get('/payment/fail', 'TransactionsController@Fail');

public function Ok( Request $request )
{
    $transId = $request->get('trans_id');

    if ( isset( $transId ) )
    {

        return $transId;

    }

}

3 个答案:

答案 0 :(得分:65)

由于版本 5.1 ,Laravel的 VerifyCsrfToken 中间件允许指定从CSRF验证中排除的路由。为了实现这一目标,您需要在 App \ Http \ Middleware \ VerifyCsrfToken.php 类中将路径添加到 $ except 数组:

<?php namespace App\Http\Middleware;

use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as BaseVerifier;

class VerifyCsrfToken extends BaseVerifier
{
  protected $except = [
    'payment/*',
  ];
}

有关详细信息,请参阅docs

答案 1 :(得分:3)

@ jedrzej.kurylo描述的技术非常适合排除一两个页面。

如果您需要从CSRF验证中排除很多页面,并且具有更多的面向未来的能力,那么这是另一种技术。

您可以细分路线,并为每个路线应用不同的中间件。因此,您可以将付款路线放入单独的路线组中,而不对它们应用VerifyCsrfToken。就是这样。

1。创建路由文件

您会发现在routes目录中,您具有以下树:

  • routes/
  • routes/api.php
  • routes/web.php

在这里routes/payment.php创建一个新文件,并在其上添加路由:

<?php
use Illuminate\Support\Facades\Route;

Route::get('/payment/ok',   'TransactionsController@Ok');
Route::get('/payment/fail', 'TransactionsController@Fail');

2。使用RouteServiceProvider处理路线

在Laravel中,路线由app\Providers\RouteServiceProvider.php处理。您会注意到以下功能:map()mapWebRoutes()。相应地添加到此文件中(为简洁起见,我已排除了股票注释。)

    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'));
    }

注意,我们添加了一个新的中间件层。这对于下一步很重要。

3。添加一个新的中间件层

您的路由组的中间件在App\Http\Kernel.php中定义。

更新$middlewareGroups属性,并为“付款”添加一个中间条目。它可以与web完全相同,但没有 VerifyCsrfToken行。

    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',
        ],
    ];

?

现在,每当添加需要从CSRF令牌检查中排除的新路由时,请将其添加到routes/payment.php文件中。

答案 2 :(得分:3)

从Laravel 7.7开始,您可以使用方法withoutMiddleware,例如:

Route::get('/payment/ok',   'TransactionsController@Ok')->withoutMiddleware(['csrf']);
Route::get('/payment/fail', 'TransactionsController@Fail')->withoutMiddleware(['csrf']);