« | »

kusa
2010-09-13 01:07 am  

こんばんは。
虫刺され、肩こりにはタイガーバームに絶対の信頼を置くくさかべです。

さて、今日は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

Comments and Trackback are closed.

最近の投稿

Archives:

カテゴリー