Laravel の 500/419/CSRF エラーを一撃解決:セッション/トークン/ドメイン設定の勘所
Laravel でフォーム送信時に突然「419 Page Expired」や「500 Internal Server Error」が発生して困った経験はありませんか?特に本番環境にデプロイした直後や、ドメイン変更後にこれらのエラーが頻発するケースが多いんですよね。
この記事では、Laravel の CSRF トークンに関連する 500 エラーと 419 エラーの原因を徹底解説し、セッション設定やドメイン設定の勘所を具体的なコード例とともにお伝えします。初心者の方でもすぐに実践できるよう、段階的に解説していきますので、ぜひ最後までお付き合いください。
背景
Laravel のセキュリティ機能と CSRF 保護
Laravel は Web アプリケーションのセキュリティを重視して設計されており、その中でも CSRF(Cross-Site Request Forgery)攻撃からアプリケーションを守る仕組みが標準で組み込まれています。
CSRF 攻撃とは、悪意のある第三者が正規ユーザーになりすまして、意図しない操作を実行させる攻撃手法です。例えば、ユーザーがログイン中のサイトに対して、別のサイトから不正なリクエストを送信するといった攻撃が該当しますね。
Laravel はこの攻撃を防ぐため、すべての POST、PUT、PATCH、DELETE リクエストに対して CSRF トークンの検証を自動的に行います。
CSRF トークンの仕組み
CSRF トークンは、フォーム送信時にサーバー側で生成される一意の文字列です。このトークンをフォームに埋め込み、送信時にサーバー側で検証することで、正規のリクエストかどうかを判断できます。
以下の図で、CSRF トークンの基本的な流れを確認しましょう。
mermaidsequenceDiagram
participant User as ユーザー
participant Browser as ブラウザ
participant Laravel as Laravel アプリ
participant Session as セッションストア
User->>Browser: フォームページを要求
Browser->>Laravel: GET リクエスト
Laravel->>Session: トークン生成/保存
Session-->>Laravel: トークン返却
Laravel-->>Browser: HTML + CSRF トークン
Browser-->>User: フォーム表示
User->>Browser: フォーム送信
Browser->>Laravel: POST + CSRF トークン
Laravel->>Session: トークン検証
alt トークン一致
Session-->>Laravel: OK
Laravel-->>Browser: 処理成功
else トークン不一致
Session-->>Laravel: NG
Laravel-->>Browser: 419 エラー
end
図で理解できる要点:
- CSRF トークンはセッションストアに保存される
- フォーム送信時にトークンの一致を検証する
- トークン不一致の場合は 419 エラーが返される
セッション管理の重要性
CSRF トークンはセッションに保存されるため、セッション管理が適切に行われていないと、トークンの検証が失敗してしまいます。Laravel のセッション設定は .env ファイルや config/session.php で管理されており、ストレージドライバー(file、database、redis など)やセッションの有効期限などを細かく制御できるんですよね。
特に本番環境では、セッションドライバーの選択やドメイン設定が重要になってきます。開発環境では問題なく動作していたのに、本番環境でエラーが発生する原因の多くは、このセッション設定の違いにあるんです。
課題
419 Page Expired エラーの発生パターン
419 エラーは「CSRF token mismatch」を意味し、以下のような状況で頻繁に発生します。
パターン 1:セッションタイムアウト
ユーザーがフォームを開いたまま長時間放置し、セッションの有効期限が切れた状態でフォームを送信すると、サーバー側に保存されていた CSRF トークンが削除されているため、検証に失敗します。
パターン 2:ドメイン/サブドメイン設定の不一致
www.example.com と example.com を異なるドメインとして扱ってしまうケースや、サブドメイン間でセッションが共有されていない場合に発生しますね。
パターン 3:セッションストレージの問題
セッションファイルの保存先ディレクトリに書き込み権限がない、Redis や Memcached との接続が切れているなど、セッションストレージ自体に問題がある場合です。
以下の図で、419 エラーが発生する主な原因を整理します。
mermaidflowchart TB
start["フォーム送信"] --> check1{"セッション<br/>有効期限内?"}
check1 -->|No| error419a["419 エラー<br/>セッションタイムアウト"]
check1 -->|Yes| check2{"ドメイン<br/>設定一致?"}
check2 -->|No| error419b["419 エラー<br/>ドメイン不一致"]
check2 -->|Yes| check3{"セッション<br/>ストレージ正常?"}
check3 -->|No| error419c["419 エラー<br/>ストレージ障害"]
check3 -->|Yes| check4{"CSRF トークン<br/>一致?"}
check4 -->|No| error419d["419 エラー<br/>トークン不一致"]
check4 -->|Yes| success["処理成功"]
style error419a fill:#ff6b6b
style error419b fill:#ff6b6b
style error419c fill:#ff6b6b
style error419d fill:#ff6b6b
style success fill:#51cf66
図で理解できる要点:
- 419 エラーには複数の発生原因がある
- セッション、ドメイン、ストレージの各層で問題が発生する可能性
- 原因の特定には段階的なチェックが必要
500 Internal Server Error の発生パターン
500 エラーは、サーバー側で予期しない問題が発生した際に返されます。CSRF 関連で 500 エラーが発生する主なパターンは以下の通りです。
エラーコード:HTTP 500
plaintextRuntimeException: The session store has not been set on the request.
発生条件: セッションミドルウェアが正しく登録されていない、または実行順序が不適切な場合
エラーコード:HTTP 500
plaintextErrorException: file_put_contents(/path/to/storage/framework/sessions/xxxxx): failed to open stream: Permission denied
発生条件: セッションファイルの保存先ディレクトリに書き込み権限がない場合
エラーコード:HTTP 500
plaintextPredis\Connection\ConnectionException: Connection refused [tcp://127.0.0.1:6379]
発生条件: セッションドライバーに Redis を使用しているが、Redis サーバーが起動していない、または接続できない場合
複数ドメイン環境での課題
SPA(Single Page Application)と API を分離している構成や、マイクロサービスアーキテクチャを採用している場合、クロスドメインでの CSRF トークン管理が必要になります。
この場合、単純な CSRF トークン検証では対応できず、Laravel Sanctum や Passport などのトークンベース認証を組み合わせる必要があるんですよね。
解決策
セッション設定の最適化
まず、.env ファイルでセッション関連の設定を確認しましょう。以下は本番環境で推奨される基本設定です。
.env ファイルの設定
plaintextSESSION_DRIVER=redis
SESSION_LIFETIME=120
SESSION_DOMAIN=.example.com
SESSION_SECURE_COOKIE=true
SESSION_HTTP_ONLY=true
SESSION_SAME_SITE=lax
各設定項目の意味を説明します。
SESSION_DRIVER
セッションの保存先を指定します。本番環境では redis や database の使用を推奨しますが、小規模なアプリケーションでは file でも問題ありません。
| # | ドライバー | 特徴 | 推奨環境 |
|---|---|---|---|
| 1 | file | ファイルシステムに保存 | 開発環境、小規模アプリ |
| 2 | redis | 高速、スケーラブル | 本番環境(推奨) |
| 3 | database | DB に保存、永続化が容易 | 中規模以上のアプリ |
| 4 | memcached | 高速だが揮発性 | 高トラフィック環境 |
| 5 | array | テスト専用 | 自動テスト |
SESSION_LIFETIME
セッションの有効期限を分単位で指定します。120 分(2 時間)が一般的ですが、セキュリティ要件に応じて調整してください。
SESSION_DOMAIN
ドメイン設定は特に重要です。先頭にドット(.)を付けることで、サブドメイン間でセッションを共有できます。
config/session.php の詳細設定
.env で設定した値は config/session.php で読み込まれます。必要に応じて、このファイルで詳細なカスタマイズが可能です。
php<?php
return [
'driver' => env('SESSION_DRIVER', 'file'),
'lifetime' => env('SESSION_LIFETIME', 120),
'expire_on_close' => false,
'encrypt' => false,
'files' => storage_path('framework/sessions'),
];
上記は基本的な設定例ですが、expire_on_close を true に設定すると、ブラウザを閉じた時点でセッションが削除されます。
ドメイン設定の最適化
ドメイン設定は、セッションとクッキーの動作に大きく影響します。以下のケース別に適切な設定を見ていきましょう。
ケース 1:単一ドメインのみ使用
https://example.com のみでアプリケーションを運用する場合です。
plaintextSESSION_DOMAIN=example.com
この設定では、example.com でのみセッションが有効になります。
ケース 2:www ありなしの両方に対応
https://example.com と https://www.example.com の両方でアクセスを許可する場合、先頭にドットを付けます。
plaintextSESSION_DOMAIN=.example.com
この設定により、example.com、www.example.com、api.example.com など、すべてのサブドメインでセッションが共有されるんですよね。
ケース 3:複数のサブドメインで共有
管理画面を admin.example.com、API を api.example.com で運用している場合も、先頭にドットを付けることでセッションを共有できます。
plaintextSESSION_DOMAIN=.example.com
CSRF トークンの適切な埋め込み
Blade テンプレートでフォームを作成する際は、必ず @csrf ディレクティブを使用します。
Blade テンプレートでの基本的な使い方
php<form method="POST" action="/submit">
@csrf
<input type="text" name="username">
<button type="submit">送信</button>
</form>
@csrf ディレクティブは、以下の hidden フィールドを自動生成します。
html<input
type="hidden"
name="_token"
value="ランダムな文字列"
/>
このトークンがサーバー側で検証され、一致しない場合は 419 エラーが返されます。
JavaScript(Axios)での CSRF トークン送信
SPA や Ajax を使用する場合は、meta タグでトークンを設定し、JavaScript 側で読み取る方法が一般的です。
まず、Blade テンプレートの <head> セクションに meta タグを追加します。
html<head>
<meta name="csrf-token" content="{{ csrf_token() }}" />
</head>
次に、JavaScript で Axios のデフォルトヘッダーに設定します。
javascript// CSRF トークンを取得
const token = document
.querySelector('meta[name="csrf-token"]')
.getAttribute('content');
// Axios のデフォルトヘッダーに設定
axios.defaults.headers.common['X-CSRF-TOKEN'] = token;
これで、すべての Axios リクエストに自動的に CSRF トークンが含まれるようになります。
fetch API での CSRF トークン送信
fetch API を使用する場合は、各リクエストごとにヘッダーを設定します。
javascriptconst token = document
.querySelector('meta[name="csrf-token"]')
.getAttribute('content');
fetch('/api/data', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-TOKEN': token,
},
body: JSON.stringify({ data: 'value' }),
})
.then((response) => response.json())
.then((data) => console.log(data));
セッションストレージの権限設定
セッションドライバーに file を使用している場合、ストレージディレクトリの権限設定が重要です。
権限エラーの確認
以下のコマンドで、現在の権限を確認できます。
bashls -la storage/framework/sessions
Web サーバーのユーザー(通常は www-data や nginx)が書き込めるよう、適切な権限を設定します。
権限の修正
bash# ストレージディレクトリの所有者を変更
sudo chown -R www-data:www-data storage
# 適切な権限を設定
sudo chmod -R 775 storage
sudo chmod -R 775 bootstrap/cache
上記のコマンドで、Web サーバーがセッションファイルを読み書きできるようになります。
Redis を使用したセッション管理
大規模なアプリケーションや、複数サーバーでの負荷分散を行う場合は、Redis によるセッション管理が最適です。
Redis のインストールと設定
まず、Redis サーバーがインストールされていることを確認します。
bash# Redis のインストール(Ubuntu/Debian の場合)
sudo apt-get install redis-server
# Redis の起動確認
redis-cli ping
PONG と返答があれば、Redis は正常に動作しています。
次に、Laravel で Redis を使用するための PHP 拡張機能をインストールします。
bash# Predis パッケージのインストール
composer require predis/predis
または、PHP Redis 拡張をインストールする方法もあります。
bash# phpredis 拡張のインストール
sudo pecl install redis
.env ファイルの設定
Redis をセッションドライバーとして使用するよう .env を更新します。
plaintextSESSION_DRIVER=redis
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
リモートの Redis サーバーを使用する場合は、REDIS_HOST と REDIS_PASSWORD を適切に設定してください。
Redis 接続の確認
以下のコマンドで、Laravel から Redis に接続できるか確認します。
bashphp artisan tinker
Tinker 内で以下を実行します。
phpRedis::connection()->ping();
+PONG と表示されれば、接続成功です。
ミドルウェアの確認と調整
CSRF 保護はミドルウェアによって実装されています。app/Http/Kernel.php で正しく設定されているか確認しましょう。
Kernel.php の web ミドルウェアグループ
phpprotected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
];
上記の順序が重要で、StartSession が VerifyCsrfToken より前に実行される必要があります。セッションが開始されていないと、CSRF トークンの検証ができないためです。
特定ルートの CSRF 検証除外
API エンドポイントなど、CSRF 検証を除外したいルートがある場合は、VerifyCsrfToken ミドルウェアをカスタマイズします。
php<?php
namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware;
class VerifyCsrfToken extends Middleware
{
/**
* CSRF 検証から除外する URI
*
* @var array
*/
protected $except = [
'api/*',
'webhook/*',
];
}
上記の設定により、/api/ と /webhook/ 配下のルートは CSRF 検証がスキップされます。ただし、セキュリティリスクが高まるため、慎重に設定してくださいね。
具体例
実際のエラーと解決プロセス
ここでは、実際に発生したエラーケースと、その解決プロセスを段階的に見ていきます。
ケース 1:本番環境デプロイ後の 419 エラー
エラーコード:HTTP 419
plaintext419 Page Expired
The page has expired due to inactivity. Please refresh and try again.
発生条件
開発環境では問題なく動作していたフォーム送信が、本番環境にデプロイした直後から 419 エラーを返すようになった。
原因調査
まず、Laravel のログファイルを確認します。
bashtail -f storage/logs/laravel.log
ログに以下のようなエラーが記録されていました。
plaintext[2025-12-12 10:15:23] production.ERROR: TokenMismatchException: CSRF token mismatch.
次に、ブラウザの開発者ツールで Cookie を確認すると、laravel_session クッキーが設定されていないことが判明しました。
解決方法
.env ファイルのドメイン設定を確認したところ、SESSION_DOMAIN が設定されていませんでした。
修正前:
plaintextSESSION_DRIVER=file
SESSION_LIFETIME=120
修正後:
plaintextSESSION_DRIVER=file
SESSION_LIFETIME=120
SESSION_DOMAIN=.example.com
この変更後、キャッシュをクリアして設定を反映します。
bashphp artisan config:clear
php artisan cache:clear
再度フォーム送信を試したところ、正常に動作するようになりました。
ケース 2:セッションファイル権限エラーによる 500 エラー
エラーコード:HTTP 500
plaintextErrorException: file_put_contents(/var/www/html/storage/framework/sessions/abc123): failed to open stream: Permission denied in /var/www/html/vendor/laravel/framework/src/Illuminate/Filesystem/Filesystem.php:122
発生条件
新しいサーバーにアプリケーションをデプロイした直後、すべてのページで 500 エラーが発生。
原因調査
エラーメッセージから、セッションファイルの書き込み権限がないことが明らかでした。ストレージディレクトリの権限を確認します。
bashls -la storage/framework/sessions
結果:
plaintextdrwxr-xr-x 2 root root 4096 Dec 12 10:00 sessions
所有者が root になっており、Web サーバー(www-data)が書き込めない状態でした。
解決方法
所有者と権限を適切に設定します。
bash# 所有者を www-data に変更
sudo chown -R www-data:www-data storage bootstrap/cache
# 書き込み権限を付与
sudo chmod -R 775 storage bootstrap/cache
さらに、SELinux が有効な環境では、以下のコマンドも必要になる場合があります。
bashsudo chcon -R -t httpd_sys_rw_content_t storage bootstrap/cache
この修正後、アプリケーションは正常に動作するようになりました。
ケース 3:Redis 接続エラーによる 500 エラー
エラーコード:HTTP 500
plaintextPredis\Connection\ConnectionException: Connection refused [tcp://127.0.0.1:6379] in /var/www/html/vendor/predis/predis/src/Connection/StreamConnection.php:248
発生条件
本番環境で Redis をセッションドライバーとして使用しているが、突然すべてのリクエストで 500 エラーが発生するようになった。
原因調査
Redis サーバーの状態を確認します。
bashsudo systemctl status redis
結果:
plaintext● redis.service - Advanced key-value store
Loaded: loaded (/lib/systemd/system/redis.service; enabled; vendor preset: enabled)
Active: inactive (dead) since Thu 2025-12-12 09:45:00 UTC; 30min ago
Redis サーバーが停止していることが判明しました。
解決方法
まず、Redis サーバーを起動します。
bashsudo systemctl start redis
sudo systemctl enable redis
次に、Laravel のキャッシュをクリアします。
bashphp artisan config:clear
php artisan cache:clear
さらに、Redis の自動起動設定を確認し、サーバー再起動時にも Redis が自動的に起動するよう設定します。
bash# 自動起動の有効化
sudo systemctl enable redis
# 起動確認
sudo systemctl is-enabled redis
この対応により、Redis との接続が回復し、アプリケーションは正常に動作するようになりました。
ケース 4:クロスドメイン環境での CSRF エラー
状況
フロントエンド(https://app.example.com)と API(https://api.example.com)を分離した SPA 構成で、API リクエスト時に 419 エラーが発生。
解決方法:Laravel Sanctum の導入
クロスドメイン環境では、通常の CSRF トークンではなく、Laravel Sanctum を使用したトークンベース認証が適しています。
まず、Sanctum をインストールします。
bashcomposer require laravel/sanctum
Sanctum の設定ファイルを公開します。
bashphp artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
次に、config/sanctum.php でドメイン設定を行います。
php'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf(
'%s%s',
'localhost,localhost:3000,127.0.0.1,127.0.0.1:8000,::1',
env('APP_URL') ? ','.parse_url(env('APP_URL'), PHP_URL_HOST) : ''
))),
.env に以下を追加します。
plaintextSANCTUM_STATEFUL_DOMAINS=app.example.com,localhost:3000
これで、指定したドメインからのリクエストに対して、Cookie ベースの認証が使用できるようになります。
フロントエンド側では、API リクエスト前に CSRF クッキーを取得します。
javascript// まず CSRF クッキーを取得
await axios.get(
'https://api.example.com/sanctum/csrf-cookie'
);
// その後、通常の API リクエストを送信
const response = await axios.post(
'https://api.example.com/api/data',
{
name: 'Test',
}
);
以下の図で、Sanctum を使用した認証フローを確認しましょう。
mermaidsequenceDiagram
participant Frontend as SPA<br/>(app.example.com)
participant API as Laravel API<br/>(api.example.com)
participant Session as セッション
Frontend->>API: GET /sanctum/csrf-cookie
API->>Session: CSRF クッキー生成
Session-->>API: クッキー保存
API-->>Frontend: Set-Cookie: XSRF-TOKEN
Frontend->>Frontend: クッキーから<br/>トークン取得
Frontend->>API: POST /api/data<br/>+ X-XSRF-TOKEN ヘッダー
API->>Session: トークン検証
Session-->>API: 検証 OK
API-->>Frontend: 処理結果
図で理解できる要点:
- SPA では事前に CSRF クッキーを取得する
- クッキーのトークンをヘッダーに含めてリクエスト
- Sanctum がクロスドメインでの認証を管理
デバッグのためのチェックリスト
エラーが発生した際は、以下のチェックリストに沿って確認すると、原因を特定しやすくなります。
| # | チェック項目 | 確認コマンド/方法 | 期待される結果 |
|---|---|---|---|
| 1 | セッションドライバーの設定 | .env の SESSION_DRIVER を確認 | file/redis/database のいずれか |
| 2 | ストレージ権限 | ls -la storage/framework/sessions | www-data |
| 3 | Redis 接続 | redis-cli ping | PONG が返る |
| 4 | ドメイン設定 | .env の SESSION_DOMAIN を確認 | 正しいドメイン名 |
| 5 | ミドルウェア順序 | Kernel.php の web グループを確認 | StartSession が VerifyCsrfToken の前 |
| 6 | CSRF トークン埋め込み | Blade テンプレートに @csrf があるか | @csrf ディレクティブが存在 |
| 7 | キャッシュクリア | php artisan config:clear | キャッシュがクリアされる |
| 8 | ログ確認 | tail -f storage/logs/laravel.log | 詳細なエラー情報を確認 |
このチェックリストに従って確認すれば、ほとんどの CSRF 関連エラーは解決できるはずです。
まとめ
Laravel の 500 エラーと 419 エラーは、CSRF トークンとセッション管理に関連する問題がほとんどです。この記事では、これらのエラーの原因と解決策を、具体的なコード例とともに解説してきました。
重要なポイントをまとめますね。
セッション設定の最適化
.envでSESSION_DOMAINを適切に設定する(サブドメイン共有の場合は.example.com)- 本番環境では Redis や database ドライバーの使用を推奨
- セッションの有効期限(
SESSION_LIFETIME)をアプリケーションの要件に合わせて設定
ストレージとアクセス権限
storage/framework/sessionsディレクトリの所有者を Web サーバーユーザー(www-data など)に設定- 適切な書き込み権限(775)を付与
- Redis を使用する場合は、Redis サーバーの起動と自動起動設定を確認
CSRF トークンの適切な実装
- Blade テンプレートでは
@csrfディレクティブを使用 - JavaScript では meta タグからトークンを取得し、Axios のデフォルトヘッダーに設定
- クロスドメイン環境では Laravel Sanctum の導入を検討
デバッグのアプローチ
- Laravel のログファイル(
storage/logs/laravel.log)で詳細なエラー情報を確認 - ブラウザの開発者ツールで Cookie とリクエストヘッダーを確認
- チェックリストに沿って段階的に問題を切り分ける
これらのポイントを押さえておけば、Laravel の CSRF 関連エラーに直面しても、冷静に対処できるようになります。特に本番環境へのデプロイ前には、セッション設定とドメイン設定を念入りに確認することをお勧めします。
エラーが発生した際は、焦らずに一つずつ確認していけば、必ず解決できますので、ぜひこの記事を参考にしてみてくださいね。
関連リンク
articleLaravel の 500/419/CSRF エラーを一撃解決:セッション/トークン/ドメイン設定の勘所
articleLaravel とは?2025 年版の強み・弱み・採用判断を 30 分で総ざらい
articleGitHub Copilot で機密文字列を誤提案しないための緊急対策:ポリシーと検知ルール
articleLaravel の 500/419/CSRF エラーを一撃解決:セッション/トークン/ドメイン設定の勘所
articleConvex インデックス設計チートシート:複合キー・範囲・前方一致の定石まとめ
articleGitHub Actions “permission denied” を解く:権限不足・保護ブランチ・環境保護の罠
articleGit 歴史改変の哲学:クリーン履歴 vs 事実履歴を使い分ける判断軸
articleFFmpeg 「moov atom not found」修復術:壊れた MP4 を救う再配置テクニック
blogiPhone 17シリーズの発表!全モデルiPhone 16から進化したポイントを見やすく整理
blogGoogleストアから訂正案内!Pixel 10ポイント有効期限「1年」表示は誤りだった
blog【2025年8月】Googleストア「ストアポイント」は1年表記はミス?2年ルールとの整合性を検証
blogGoogleストアの注文キャンセルはなぜ起きる?Pixel 10購入前に知るべき注意点
blogPixcel 10シリーズの発表!全モデル Pixcel 9 から進化したポイントを見やすく整理
blogフロントエンドエンジニアの成長戦略:コーチングで最速スキルアップする方法
review今の自分に満足していますか?『持たざる者の逆襲 まだ何者でもない君へ』溝口勇児
reviewついに語られた業界の裏側!『フジテレビの正体』堀江貴文が描くテレビ局の本当の姿
review愛する勇気を持てば人生が変わる!『幸せになる勇気』岸見一郎・古賀史健のアドラー実践編で真の幸福を手に入れる
review週末を変えれば年収も変わる!『世界の一流は「休日」に何をしているのか』越川慎司の一流週末メソッド
review新しい自分に会いに行こう!『自分の変え方』村岡大樹の認知科学コーチングで人生リセット
review科学革命から AI 時代へ!『サピエンス全史 下巻』ユヴァル・ノア・ハラリが予見する人類の未来