verifycsrftoken tokenmismatchexception php laravel exception-handling csrf laravel-5

tokenmismatchexception - csrf token php



Laravel catch TokenMismatchException (5)

¿Puede atrapar TokenMismatchException usando try catch block? En lugar de mostrar la página de depuración que muestra la "TokenMismatchException en VerifyCsrfToken.php línea 46 ...", quiero que muestre la página real y solo muestre un mensaje de error.

No tengo problemas con el CSRF, solo quiero que muestre la página en lugar de la página de depuración.

Para replicar (usando Firefox): Pasos:

  1. Abrir página ( http://example.com/login )
  2. Borrar cookies (dominio, ruta, sesión). Estoy usando el complemento de la barra de herramientas para desarrolladores web aquí.
  3. Enviar formulario

Resultados reales: aparece la página "Vaya, parece que algo salió mal". Resultados esperados: Todavía muestra la página de inicio de sesión y luego pasa un error de "Token mismatch" o algo así.

Tenga en cuenta que cuando borre las cookies, no actualicé la página para que el token genere una nueva clave y la fuerce a error.

ACTUALIZACIÓN (FORMULARIO AGREGADO):

<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>

Nada realmente lujoso aquí. Solo una forma ordinaria. Al igual que lo que he dicho, la forma está FUNCIONANDO perfectamente bien. Solo cuando indiqué los pasos anteriores, se produce un error debido a que TOKEN está vencido. Mi pregunta es, ¿debería la forma comportarse de esa manera? Quiero decir, ¿cuándo borro las cookies y la sesión, necesito volver a cargar la página también? ¿Es así como funciona CSRF aquí?


En lugar de tratar de atrapar la excepción, solo redireccione al usuario a la misma página y haga que repita la acción nuevamente.

Utilice este código en la aplicación / 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.''); } }


LOL

BOB En las solicitudes AJAX puede responder al cliente utilizando la función abort () y luego manejar la respuesta en el lado del cliente usando AJAX jqXHR.status muy fácilmente, por ejemplo, mostrando un mensaje y actualizando la página. No olvides capturar el código de estado HTML en el evento jQuery ajaxComplete:


Laravel 5.2: Modifique App / Exceptions / Handler.php de la siguiente manera:

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

En las solicitudes AJAX puede responder al cliente utilizando la función abort () y luego manejar la respuesta en el lado del cliente utilizando AJAX jqXHR.status muy fácilmente, por ejemplo, mostrando un mensaje y actualizando la página. No olvides capturar el código de estado HTML en el evento jQuery ajaxComplete:

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


Puede manejar Excepción TokenMismatchException en App / Exceptions / Handler.php

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


Una mejor solución de Laravel 5

en App / Exceptions / Handler.php
Devuelva al usuario al formulario con un nuevo token CSRF válido, para que pueda volver a enviar el formulario sin llenar el formulario nuevamente.

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

También me gusta esta idea:

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