先日、既存のセッションクッキーにsecure属性だったり、httponly属性がついてないことに気づきまして既存実装を修正しようとしていました。FWの機能ではセッションに属性をつけることができないことがわかり、session_set_cookie_params関数を利用してデータを入れようとしました。その際、私の認識が甘かったこともあり、ドメインにHttpHost名を入れました。lifetimeの値にsetcookie関数と同様にtime()を足してしまいました。(その結果有効期限が2071年くらいになる)何が起きたか元々あったdomain.localhostのセッションクッキーと.domain.localhostのセッションクッキーがブラウザ内にできました。普通はできないはずだと思うのですが、色々試してたところ、できてしまいました。(一応同じ状況を作るなら自分で勝手にsetcookieしちゃえば同じ状況を作れます)これは良くないと思ったので、session_set_cookie_params関数のdomain属性を空値に変更をしました。(同時にtime()の部分も削除しました)そうするとですね、ブラウザが送ってくる値が.domain.localhostのセッションIdになってしまいました。(どうやら古いものを優先的に送る?←違いました)問題になったこと表示の際にはセッションに存在しているcsrfのトークンの値が、送信時にはサーバー側にはセッションにcsrfトークンのキーが別の値になっていることがわかりました。POST時にどうやら変わってしまってる様子です。HeaderのCookieに同じSessionキーのもので、値が異なるものが2つ送られていました。Cookieに関して、色々調べてみると以下のサイトにあたりました。ヘッダでブラウザから送信されるクッキーの順序は以下のように決まります。ヘッダの中に現れることがありうるので注意してください。いうことでですね、.domain.localhostのほうのセッションキーのほうが先に送られることになります。PHPは後にある同じセッションキーを見ないようで、先にある.domain.localhostのセッション値を読もうとしてしまいます。結果起きてしまうこと.domain.localhostの方のセッション値を読んでしまうことがわかりました。そこで、セッション自体をサーバーから削除してみると、問題が広がります。今回、domainの値を戻したのが原因が広まってしまったのですが優先されて来るのは.domain.localhostのセッション値アプリケーションは存在しないことが分かったので、セッションを新しく作ってブラウザにdomain.localhostのセッションクッキーを作らせる作らせるものの、.domain.localhostのほうが文字数が1文字長いので優先されるのは.domain.localhostになります。2に戻るこのようになってしまう結果、csrfのトークンの検証ができなくなったということですね。作りによってはですが、ログインページ等でログインしていたらマイページに飛ばしますという処理を書いていた場合、ログインページに来たときには自動的にマイページに飛ばそうとするが、セッションがdomain.localhostの方に登録されるので.domain.localhostには存在しないからまたログインページに戻ってくるといった無限ループに繋がります。ここでですね、.domain.localhostのセッションクッキーの期限がブラウザセッションになっていたりすればブラウザの再起動で直せたのでしょうけど、最初に書いたとおり、lifetimeを設定しようとして間違えてtime()関数を入れてしまったことがよりこの問題を複雑化してしまうことになりました。setcookieでの削除も考えましたが、先程の流れの通り、2でSetCookieで作られるからかsetcookieでの削除はできない感じでした。(もしかしたらやり方があるのかもしれません。header関数だとreplaceをfalseにしたら行ける気がしたんですが、なぜかうまく行きませんでした)結果おそらくこれを対処するためには、セッションキーをそもそも変えてしまうしか無いような気がしました。この問題の厄介なところは、すぐには原因がわからないことです。(元のcookieが残っていればなんとかなったりする)今回は本番に反映してないので影響はなかったのですが、cookieの扱いには気をつけましょう。ありますバッジを贈って著者を応援しようバッジを受け取った著者にはZennから現金やAmazonギフトカードが還元されます。Proよくある質問LinksX(Twitter)GitHubメディアキットLegal利用規約プライバシーポリシ。