【问题标题】:Laravel - adding VerifyCsrfToken to controller getting ajax requestLaravel - 将 VerifyCsrfToken 添加到控制器获取 ajax 请求
【发布时间】:2018-05-24 11:32:32
【问题描述】:

我正在创建一个接收 AJAX 请求的控制器,并且从 Laravel 文档中,我可以发送带有 X-Csrf 令牌的标头 https://laravel.com/docs/5.5/csrf#csrf-x-csrf-token

在我的控制器上我有这样的东西:

 public function checkPromotion(Request $request)
{

    try {
        $this->middleware('VerifyCsrfToken');
    }
    catch (TokenMismatchException $e){
        return response()->json(['error' => 'Error Token Provided']);
    }


}

}

当我尝试向这个控制器发送一个空白的发布请求时,响应是空白的。

【问题讨论】:

    标签: php ajax laravel csrf csrf-protection


    【解决方案1】:

    这里有三个问题:

    1. 如果要在控制器中添加中间件,则必须在构造函数中进行。

    2. 开箱即用,您无法在控制器操作中处理中间件异常。您需要在您的 \App\Exceptions\Handler 课程中使用 handle the exception。当令牌验证失败时,该类的handle 方法将收到TokenMismatchException

    3. 字符串'VerifyCsrfToken' 不是引用中间件的有效方式。

    关于#3,middleware 方法采用middleware group 的名称,或特定中间件的 FQCN。

    以下应该有效:

    $this->middleware(\App\Http\Middleware\VerifyCsrfToken::class)
    

    (我假设您使用的是默认的 App 命名空间)

    如果你得到一个“Session store not set on request”异常,那是因为没有 StartSession 中间件就不能使用 CSRF 中间件。

    您真正想要的很可能是网络中间件:

    $this->middleware('web')
    

    这将包括 CSRF 中间件、会话启动中间件和其他一些中间件(有关详细信息,请参阅您的 http 内核)。

    如果需要,您可以在 VerifyCsrfToken 类中使用 $except 数组 exclude routes from CSRF verification

    【讨论】:

    • 我试过了,仍然得到空白响应尝试 { $this->middleware(VerifyCsrfToken::class); } catch (TokenMismatchException $e){ return response()->json(['error' => 'Error Token Provided']); }
    • @user2873860 你导入了VerifyCsrfToken吗?
    • 它不起作用,我尝试了两种方式 if (!$this->middleware(VerifyCsrfToken::class)){ return response()->json(['error' => 'Error Token假如']); } 尝试 { $this->middleware(VerifyCsrfToken::class); } catch (TokenMismatchException $e){ return response()->json(['error' => 'Error Token Provided']); }
    • @user2873860 刚刚注意到您在控制器操作中添加中间件,您必须在构造函数中进行。
    • 我尝试添加类构造,在 Request.php 行 905 中显示 RuntimeException 错误:未按请求设置会话存储。但是我需要以一种方法而不是整个班级使用它,有什么办法吗?
    【解决方案2】:

    Controller 上的 middleware 方法正在控制器上的数组中注册一个中间件。那个中间件当时没有运行。

    当在构造函数中调用此方法时,在控制器被解析为能够构建当前路由/操作所需的中间件堆栈后,路由器/路由集合将有权访问getMiddleware 方法。

    您可能希望在异常处理程序App\Exceptions\Handler 中处理此异常。

    Laravel 5.5 Docs - Errors - The Exception Handler - Render Method

    public function render($request, Exception $exception)
    {
        if ($exception instanceof \Illuminate\Session\TokenMismatchException) {
            return response()->json(['error' => 'Error Token Provided']);
        }
    
        return parent::render($request, $exception);
    }
    

    【讨论】:

    • 你能解释一下我是如何处理 App\Exceptions\Handler 的吗?
    • 当表单提交给控制器时,laravel 默认如何验证它的令牌,我需要让我的控制器处理 ajax 请求,因为它是一个表单,需要一个令牌头
    • 正如 mtinsley 指出的 web 中间件组...它提供会话和 VerifyCsrfToken 中间件...您在routes/web.php 中的所有路由应该已经拥有整个web 中间件组默认应用
    【解决方案3】:
    protected function tokensMatch($request)
    {
        // If request is an ajax request, then check to see if token matches token provider in
        // the header. This way, we can use CSRF protection in ajax requests also.
        $token = $request->ajax() ? $request->header('X-CSRF-Token') : $request->input('_token');
    
        return $request->session()->token() == $token;
    }
    

    在VerifyCsrfToken.php中添加这个函数

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-02-26
      • 2019-02-08
      • 2018-02-28
      • 1970-01-01
      • 1970-01-01
      • 2020-08-06
      • 2018-03-16
      • 2020-10-28
      相关资源
      最近更新 更多