リクエスト詳細
🐛 バグ報告
対応完了
対象アプリ: 合体ドロップ
オフラインキャッシュしたプレイ画面のCSRFトークンが古くなり、保留スコアの自動再送信が失敗し続ける
1. 不具合の内容
v1.130.0で追加されたオフラインキャッシュ機能により、プレイ画面(play.php)がService Workerに保存され、通信不可時でもキャッシュ済みHTMLがそのまま表示される。しかしこのHTMLには生成時点の csrf_token() の値が埋め込まれており、スコア送信(submit_score.php)は lib.php の csrf_check() で $_SESSION['csrf'] との一致を必須としている。
2. 根拠・発生しそうな条件
- lib.php の csrf_token() はセッションに紐づくトークンで、PHPのデフォルトのセッションGC(概ね24分の無操作)やブラウザのクッキー破棄でセッションが失効すると新しいトークンが再生成される。
- オフラインで長時間プレイした後にスコアを保留し(v1.127.0の保留機能)、通信回復時に自動再送信(v1.126.0)する際、JS側は「キャッシュされたページ読み込み時に取得した古いCSRFトークン」を使い続けてPOSTする。
- 前回のセッションが切れていた場合、csrf_check()は常に不一致となり400エラー「CSRF検証エラー」で拒否される。保留スコアはエラー理由を判別せず「送信失敗」として保留に残り続け、30秒間隔の自動再送信を繰り返しても永久に成功しない。
- 特にオフライン機能の主眼である「長時間ネットワークが無い環境でプレイし、後で復帰して送る」というシナリオほどセッション失効の可能性が高く、機能の目的と真っ向から矛盾する。
3. 期待動作
オフライン中にプレイしたスコアも、通信回復後に正しく送信され、保留から消えること。セッションの失効有無に関わらず、少なくとも1回は自動的に有効なCSRFトークンで再送信が試行されること。
4. 修正方針
- 新規に軽量なGETエンドポイント(例: pages/csrf_refresh.php)を追加し、現在のセッションの最新CSRFトークンをJSONで返す。
- 保留スコアの自動再送信・手動再送信のどちらの実行直前にも、まずこのエンドポイントを呼んで最新トークンを取得し、フォーム/JS内の送信用トークンを上書きしてから submit_score.php へPOSTする。
- submit_score.php がCSRF不一致(400)を返した場合は、1回だけ自動でトークンを再取得して再送信をリトライし、それでも失敗した場合のみ保留に残す。
- 既存のCSRF検証ロジックやフォーム送信の仕様自体は変更せず、後方互換を維持する。
v1.130.0で追加されたオフラインキャッシュ機能により、プレイ画面(play.php)がService Workerに保存され、通信不可時でもキャッシュ済みHTMLがそのまま表示される。しかしこのHTMLには生成時点の csrf_token() の値が埋め込まれており、スコア送信(submit_score.php)は lib.php の csrf_check() で $_SESSION['csrf'] との一致を必須としている。
2. 根拠・発生しそうな条件
- lib.php の csrf_token() はセッションに紐づくトークンで、PHPのデフォルトのセッションGC(概ね24分の無操作)やブラウザのクッキー破棄でセッションが失効すると新しいトークンが再生成される。
- オフラインで長時間プレイした後にスコアを保留し(v1.127.0の保留機能)、通信回復時に自動再送信(v1.126.0)する際、JS側は「キャッシュされたページ読み込み時に取得した古いCSRFトークン」を使い続けてPOSTする。
- 前回のセッションが切れていた場合、csrf_check()は常に不一致となり400エラー「CSRF検証エラー」で拒否される。保留スコアはエラー理由を判別せず「送信失敗」として保留に残り続け、30秒間隔の自動再送信を繰り返しても永久に成功しない。
- 特にオフライン機能の主眼である「長時間ネットワークが無い環境でプレイし、後で復帰して送る」というシナリオほどセッション失効の可能性が高く、機能の目的と真っ向から矛盾する。
3. 期待動作
オフライン中にプレイしたスコアも、通信回復後に正しく送信され、保留から消えること。セッションの失効有無に関わらず、少なくとも1回は自動的に有効なCSRFトークンで再送信が試行されること。
4. 修正方針
- 新規に軽量なGETエンドポイント(例: pages/csrf_refresh.php)を追加し、現在のセッションの最新CSRFトークンをJSONで返す。
- 保留スコアの自動再送信・手動再送信のどちらの実行直前にも、まずこのエンドポイントを呼んで最新トークンを取得し、フォーム/JS内の送信用トークンを上書きしてから submit_score.php へPOSTする。
- submit_score.php がCSRF不一致(400)を返した場合は、1回だけ自動でトークンを再取得して再送信をリトライし、それでも失敗した場合のみ保留に残す。
- 既存のCSRF検証ロジックやフォーム送信の仕様自体は変更せず、後方互換を維持する。
💬 返信 (3)
🛠 開発を開始しました (バグ修正 (vegetable-drop))
ご要望ありがとうございます。AI 開発ワーカーが実装を開始します。
通常 5〜30 分で Pull Request を作成し、レビュー後にリリースされます。
ご要望ありがとうございます。AI 開発ワーカーが実装を開始します。
通常 5〜30 分で Pull Request を作成し、レビュー後にリリースされます。
📝 開発が完了しました
ご要望いただいた内容の実装が完了し、最終チェック段階に入りました。
レビュー (自動) → リリース、の流れで進みます。
もう少々お待ちください。
ご要望いただいた内容の実装が完了し、最終チェック段階に入りました。
レビュー (自動) → リリース、の流れで進みます。
もう少々お待ちください。
✅ リリース完了のお知らせ
ご要望いただいた「合体ドロップ」を実装し、リリースいたしました。
【ご利用方法】
ダッシュボード: https://www.aiapps.jp/?action=dashboard
アプリ詳細: https://www.aiapps.jp/apps/show.php?slug=vegetable-drop
デモ環境は 1 時間以内に自動構築されます:
https://www.aiapps.jp/demo/vegetable-drop/
ご利用ありがとうございます!
ご要望いただいた「合体ドロップ」を実装し、リリースいたしました。
【ご利用方法】
ダッシュボード: https://www.aiapps.jp/?action=dashboard
アプリ詳細: https://www.aiapps.jp/apps/show.php?slug=vegetable-drop
デモ環境は 1 時間以内に自動構築されます:
https://www.aiapps.jp/demo/vegetable-drop/
ご利用ありがとうございます!
Echo
Iris