Laravel - 将 VerifyCsrfToken 添加到控制器获取 ajax 请求
Posted
技术标签:
【中文标题】Laravel - 将 VerifyCsrfToken 添加到控制器获取 ajax 请求【英文标题】:Laravel - adding VerifyCsrfToken to controller getting ajax request 【发布时间】: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']);
当我尝试向这个控制器发送一个空白的发布请求时,响应是空白的。
【问题讨论】:
【参考方案1】:这里有三个问题:
如果要在控制器中添加中间件,则必须在构造函数中进行。
开箱即用,您无法在控制器操作中处理中间件异常。您需要在您的 \App\Exceptions\Handler
课程中使用 handle the exception。当令牌验证失败时,该类的handle
方法将收到TokenMismatchException
。
字符串'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中添加这个函数
【讨论】:
以上是关于Laravel - 将 VerifyCsrfToken 添加到控制器获取 ajax 请求的主要内容,如果未能解决你的问题,请参考以下文章
如何将 Laravel 安装程序“laravel/installer”更新到最新版本?
无法将 Laravel 连接到 MailChimp(laravel 5.4)
vue.js 和 Laravel - 我们如何将 vue js 与 laravel 集成?
如何将 Laravel 身份验证添加到已启动的 Laravel 项目中?
Laravel - 为啥 laravel 要求将 .env.example 重命名为 .env 而 .env 已经存在?