多くの原因はCSRFトークンを記述していない場合で発生する
ググってみると多くの場合はフォーム内にCSRFトークンの記述漏れで発生していることが多いようです。
なのでまずはフォーム内にCSRFトークンの記述があるかを確認してください
Laravel5.6以前なら{{ csrf_field() }}
を、
Laravel5.6系以降なら@csrf
というシンプルに記述できるので、これをフォーム内に埋め込んでください。
以下Laravel5.6以前の記述例
<form method="POST" action="/profile">
{{ csrf_field() }}
...
</form>
以下Laravel5.6系以降の記述例
<form method="POST" action="/profile">
@csrf
...
</form>
以下参考になるのかもしれませんが少し情報が古いので注意
【Laravel】TokenMismatchExceptionが発生する原因 - Qiita
CSRFトークンの有効期限切れで表示される
CSRFトークンの有効期限切れで表示される場合(例えばログイン画面で長時間放置してからログインしたりする)
以下のような画面が表示され、リロードしろと促されます。
正直、この画面がでても何のことかわからないし、あまりにも突然表示されたりするので、
CSRFトークンが有効期限切れの状態でログインしたりした際、ログイン画面へリダイレクトさせる処理をapp/Exceptions/Handler.php
に記述していきます。
<?php
namespace App\Exceptions;
use Exception;
use Illuminate\Auth\AuthenticationException;
use Illuminate\Session\TokenMismatchException; // add
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
class Handler extends ExceptionHandler
{
// ...
/**
* Render an exception into an HTTP response.
*
* @param \Illuminate\Http\Request $request
* @param \Exception $exception
* @return \Illuminate\Http\Response
*/
public function render($request, Exception $exception)
{
// 「the page has expired due to inactivity. please refresh and try again」を表示させない
if ($exception instanceof TokenMismatchException) {
return redirect('/login')->with('message', 'セッションの有効期限が切れました。再度ログインしてください。');
}
return parent::render($request, $exception);
}
}
これでTokenMismatchException
が発生した場合はログイン画面へエラーメッセージとともにリダイレクトさせることができる
ステータスコード(419)の場合にリダイレクトさせる
ちなみにステータスコードで判定するようにもできるので以下のようにも書けます。
<?php
namespace App\Exceptions;
use Exception;
use Illuminate\Auth\AuthenticationException;
use Illuminate\Support\ViewErrorBag; // add
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface; // add
class Handler extends ExceptionHandler
{
// ...
/**
* Render the given HttpException.
*
* @param \Symfony\Component\HttpKernel\Exception\HttpExceptionInterface $e
* @return \Symfony\Component\HttpFoundation\Response
*/
protected function renderHttpException(HttpExceptionInterface $e)
{
$this->registerErrorViewPaths();
// 「the page has expired due to inactivity. please refresh and try again」を表示させない
if ($e->getStatusCode() === 419) {
return redirect('/login');
}
if (view()->exists($view = "errors::{$e->getStatusCode()}")) {
return response()->view($view, [
'errors' => new ViewErrorBag,
'exception' => $e,
], $e->getStatusCode(), $e->getHeaders());
}
return $this->convertExceptionToResponse($e);
}
}
ただステータスコード419
が必ずしもCSRFトークンの有効期限切れで返しているかわからないので、TokenMismatchException
が発生した場合のみログイン画面へリダイレクトさせた方がいいかなと思っていますがどうでしょう?
おわり
- もっといい方法あれば教えていただきたいです草々不一