« パソコンがちょっと愛おしくなる話。 | Webの力を実感? »
こんばんは。
虫刺され、肩こりにはタイガーバームに絶対の信頼を置くくさかべです。
さて、今日はPHPの関数 session_regenerate_id() で、
先日ハマってしまった問題について、備忘録をかねて。
session_regenerate_id() は、おもにセッションIDが盗み取られることによる
セッションハイジャックを防ぐために使用する関数です。
この関数は、タイミングによっては、古いセッションIDのままリクエストを行ってしまい
セッションが切れたように見えてしまうという問題があることは
session_regenerate_idで検索するとちらほらヒットします。
ですが、やや特殊な状況ではありますが、
先日大いにハマってしまいました。
問題となるのは、セッションをcookieで受け渡し、
session_cookie_domainをサイトルート直下以外の
.htaccessで設定して、IE8(他のバージョンでも再現するかもしれません)で
アクセスした場合です。
このような環境で、まず、サイトルート直下にあるPHPのスクリプトで
Cookieが生成されるとします。(これを「はじめのCookie」とします)
その後、session_cookie_domainの設定されたディレクトリ等にある
スクリプトでsession_regenerate_idを実行すると、
サーバーからは新たなSet-Cookieヘッダが返されるわけですが
これを、IE8では、はじめのCookieとは異なるCookieとして
受け入れてしまい(これを「ふたつめのCookie」とします)、
はじめのCookieを上書きしてくれないようです。
その後のリクエスト時には、同じCookieのキー名で異なる2つのセッションIDを
送ってしまうのですが、これを処理するPHP側は、一つめのセッションID、
つまりはじめにサイトルートで生成されたセッションIDを使用してしまいます。
また、その後session_regenerate_id()を実行すると、
ふたつめのCookieを書き換えてしまいます。
その結果、クライアント側からは、session_regenerate_id()実行後の
セッション変数が保存されないように見えてしまいます。
これを防ぐには、単純にsession_cookie_domainがサイト全体で
共通して設定されるよう、サイトルートで設定するなどするだけでOKです。
最終的にはHTTPレスポンスヘッダを眺めていて気がついたのですが
これはなかなかはまりました…。
非常にまれなケースかも知れませんがsession_regenerate_id()は、
はじめに書いたような古いIDを使用してしまうことも含め要注意ですね。
それでは。
Comment & Trackback