【问题标题】:disable csrf in laravel for specific route在 laravel 中为特定路由禁用 csrf
【发布时间】:2015-10-22 03:27:04
【问题描述】:

我有一个支付系统,数据被提交到第 3 方网站,然后被拉回......

当数据返回时,它会点击特定的 url,比如说 /ok 路由。 $_REQUEST['transaction'].

但是由于 laravel 中间件,我得到了令牌不匹配。没有办法 3rd 方支付 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;

    }

}

【问题讨论】:

  • 你使用的是什么版本的 Laravel?如果是 5.1,请参阅下面的答案。如果有些旧,请告诉我,我会更新答案,因为旧版本有办法做到这一点,只是有点复杂。
  • @jedrzej.kurylo 我可以知道如何在 Laravel 5.0 中禁用 CSRF 令牌。

标签: php laravel laravel-5 laravel-5.1


【解决方案1】:

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 了解更多信息。

【讨论】:

  • 嗨 Jedrzej,上面的方法我已经使用过,但它不适用于 laravel 5.2。我需要知道如何为 laravel 5.2 版本的上述类似解决方案禁用 API 路由的 CSRF 令牌。
  • 在 5.2 中排除 URI 的工作方式相同 - 请参阅此处的文档 laravel.com/docs/5.2/routing#csrf-excluding-uris
【解决方案2】:

@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()。相应地添加到此文件中(为简洁起见,我已排除库存 cmets)。

    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 文件中。

【讨论】:

  • 我称之为过度工程
【解决方案3】:

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

Route::get('/payment/ok',   'TransactionsController@Ok')
    ->withoutMiddleware([\App\Http\Middleware\VerifyCsrfToken::class]);

Route::get('/payment/fail', 'TransactionsController@Fail')
    ->withoutMiddleware([\App\Http\Middleware\VerifyCsrfToken::class]);

【讨论】:

  • 你应该将 csrf 字段添加到 app/Http/Kernel.php $routeMiddleware 数组中,例如 'csrf' => VerifyCsrfToken::class
  • 正如@ozal-zarbaliyev 提到的,没有名称为csrf 的中间件。只需在withoutMiddleware 函数中使用\App\Http\Middleware\VerifyCsrfToken::class
猜你喜欢
  • 2013-08-07
  • 1970-01-01
  • 2016-03-20
  • 2016-05-24
  • 2018-04-04
  • 2017-07-03
  • 2015-09-22
  • 2015-03-11
  • 2012-07-20
相关资源
最近更新 更多