【Laravel5】たまに出てくる「the page has expired due to inactivity. please refresh and try again」を表示させない


# 多くの原因はCSRFトークンを記述していない場合で発生する

ググってみると多くの場合は**フォーム内にCSRFトークンの記述漏れで発生していることが多い**ようです。
なのでまずは**フォーム内にCSRFトークンの記述があるかを確認してください**
**Laravel5.6以前**なら`{{ csrf_field() }}`を、
**Laravel5.6系以降**なら`@csrf`というシンプルに記述できるので、これを**フォーム内に埋め込んでください。**

以下**Laravel5.6以前**の記述例

```html:form.blade.php
<form method="POST" action="/profile">
    {{ csrf_field() }}
    ...
</form>
```

以下**Laravel5.6系以降**の記述例

```html:form.blade.php
<form method="POST" action="/profile">
    @csrf
    ...
</form>
```


以下参考になるのかもしれませんが**少し情報が古いので注意**
[【Laravel】TokenMismatchExceptionが発生する原因 - Qiita](https://qiita.com/sola-msr/items/e8d743d3677153a0779e)

# CSRFトークンの有効期限切れで表示される

**CSRFトークンの有効期限切れで表示される場合**（例えば**ログイン画面で長時間放置してからログインしたりする**）
以下のような画面が表示され、リロードしろと促されます。

![419.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/85815/e2814b98-52f8-30af-8686-a9e5d8681c13.png)

正直、この画面がでても何のことかわからないし、あまりにも突然表示されたりするので、
**CSRFトークンが有効期限切れの状態でログインしたりした際、ログイン画面へリダイレクトさせる処理**を`app/Exceptions/Handler.php`に記述していきます。

```laravel\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）の場合にリダイレクトさせる

ちなみにステータスコードで判定するようにもできるので以下のようにも書けます。

```laravel\app\Exceptions\Handler.php
<?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`が発生した場合のみログイン画面へリダイレクトさせた方がいいかなと思っていますがどうでしょう？


# おわり

- もっといい方法あれば教えていただきたいです草々不一

# 参考URL
- [session - Laravel "The page has expired due to inactivity" - Stack Overflow](https://stackoverflow.com/questions/49422889/laravel-the-page-has-expired-due-to-inactivity)
- [Laravel5: エラーページを共通化〜どんなステータスコードでもどんと来い！ - Qiita](https://qiita.com/M_Ishikawa/items/1f0d72fc93286109464e)