Laravel捕获TokenMismatchException

TokenMismatchException可以使用try catch块捕获吗? 而不是显示debugging页面,显示“TokenMismatchException VerifyCsrfToken.php行46 …”,我希望它显示实际的页面,只是显示一个错误信息。

我没有与CSRF的问题,我只是希望它仍然显示页面,而不是debugging页面。

复制(使用Firefox):步骤:

  1. 打开页面( http://example.com/login )
  2. 清除Cookies(域,path,会话)。 我在这里使用web开发工具栏插件。
  3. 提交表格。

实际结果:“哎呀,看起来像是出了问题”页面显示。 预期结果:仍然显示login页面,然后传递“令牌不匹配”的错误或其他东西。

请注意,当我清除cookie时,我没有刷新页面,令令牌生成一个新的密钥,并强制错误。

更新(新增表格):

<form class="form-horizontal" action="<?php echo route($formActionStoreUrl); ?>" method="post"> <input type="hidden" name="_token" value="<?php echo csrf_token(); ?>" /> <div class="form-group"> <label for="txtCode" class="col-sm-1 control-label">Code</label> <div class="col-sm-11"> <input type="text" name="txtCode" id="txtCode" class="form-control" placeholder="Code" /> </div> </div> <div class="form-group"> <label for="txtDesc" class="col-sm-1 control-label">Description</label> <div class="col-sm-11"> <input type="text" name="txtDesc" id="txtDesc" class="form-control" placeholder="Description" /> </div> </div> <div class="form-group"> <label for="cbxInactive" class="col-sm-1 control-label">Inactive</label> <div class="col-sm-11"> <div class="checkbox"> <label> <input type="checkbox" name="cbxInactive" id="cbxInactive" value="inactive" />&nbsp; <span class="check"></span> </label> </div> </div> </div> <div class="form-group"> <div class="col-sm-12"> <button type="submit" class="btn btn-primary pull-right"><i class="fa fa-save fa-lg"></i> Save</button> </div> </div> </form> 

这里没有什么真正的想法。 只是一个普通的forms。 就像我所说的,表单工作得很好。 正是当我说明上述步骤时,由于TOKEN过期而出错。 我的问题是,如果这种forms的行为呢? 我的意思是,当我清除cookies和会话时,我需要重新加载页面呢? CSRF是如何在这里工作的?

您可以处理App \ Exceptions \ Handler.php中的TokenMismatchExceptionexception

 <?php namespace App\Exceptions; use Exception; use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler; use Illuminate\Session\TokenMismatchException; class Handler extends ExceptionHandler { /** * A list of the exception types that should not be reported. * * @var array */ protected $dontReport = [ 'Symfony\Component\HttpKernel\Exception\HttpException' ]; /** * Report or log an exception. * * This is a great spot to send exceptions to Sentry, Bugsnag, etc. * * @param \Exception $e * @return void */ public function report(Exception $e) { return parent::report($e); } /** * Render an exception into an HTTP response. * * @param \Illuminate\Http\Request $request * @param \Exception $e * @return \Illuminate\Http\Response */ public function render($request, Exception $e) { if ($e instanceof TokenMismatchException){ // Redirect to a form. Here is an example of how I handle mine return redirect($request->fullUrl())->with('csrf_error',"Oops! Seems you couldn't submit form for a long time. Please try again."); } return parent::render($request, $e); } } 

一个更好的Laravel 5解决scheme

App \ Exceptions \ Handler.php中
将用户返回到具有新的有效CSRF令牌的表单,以便他们可以重新提交表单而不必重新填写表单。

 public function render($request, Exception $e) { if($e instanceof \Illuminate\Session\TokenMismatchException){ return redirect() ->back() ->withInput($request->except('_token')) ->withMessage('Your explanation message depending on how much you want to dumb it down, lol!'); } return parent::render($request, $e); } 

我也很喜欢这个想法:

https://github.com/GeneaLabs/laravel-caffeine

而不是试图抓住例外,只是将用户redirect到同一页面,并使他/她再次重复行动。

在App \ Http \ Middleware \ VerifyCsrfToken.php中使用此代码

 <?php namespace App\Http\Middleware; use Closure; use Redirect; use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as BaseVerifier; class VerifyCsrfToken extends BaseVerifier { /** * The URIs that should be excluded from CSRF verification. * * @var array */ protected $except = [ // ]; public function handle( $request, Closure $next ) { if ( $this->isReading($request) || $this->runningUnitTests() || $this->shouldPassThrough($request) || $this->tokensMatch($request) ) { return $this->addCookieToResponse($request, $next($request)); } // redirect the user back to the last page and show error return Redirect::back()->withError('Sorry, we could not verify your request. Please try again.'); } } 

Laravel 5.2:像这样修改App \ Exceptions \ Handler.php

 <?php namespace App\Exceptions; use Exception; use Illuminate\Validation\ValidationException; use Illuminate\Auth\Access\AuthorizationException; use Illuminate\Database\Eloquent\ModelNotFoundException; use Symfony\Component\HttpKernel\Exception\HttpException; use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler; use Illuminate\Session\TokenMismatchException; class Handler extends ExceptionHandler { /** * A list of the exception types that should not be reported. * * @var array */ protected $dontReport = [ AuthorizationException::class, HttpException::class, ModelNotFoundException::class, ValidationException::class, ]; /** * Report or log an exception. * * This is a great spot to send exceptions to Sentry, Bugsnag, etc. * * @param \Exception $e * @return void */ public function report(Exception $e) { parent::report($e); } /** * Render an exception into an HTTP response. * * @param \Illuminate\Http\Request $request * @param \Exception $e * @return \Illuminate\Http\Response */ public function render($request, Exception $e) { if ($e instanceof TokenMismatchException) { abort(400); /* bad request */ } return parent::render($request, $e); } } 

在AJAX请求中,您可以使用abort()函数响应客户端,然后使用AJAX jqXHR.status轻松处理客户端响应,例如通过显示消息和刷新页面。 不要忘记在jQuery ajaxComplete事件中捕获HTML状态码:

 $(document).ajaxComplete(function(event, xhr, settings) { switch (xhr.status) { case 400: status_write('Bad Response!!!', 'error'); location.reload(); } } 

大声笑

BOB在AJAX请求中,您可以使用abort()函数响应客户端,然后使用AJAX jqXHR.status轻松处理客户端响应,例如通过显示消息和刷新页面。 不要忘记在jQuery ajaxComplete事件中捕获HTML状态码: