URL埋め込み方式を用いる際のセキュリティ対策
session.use_trans_sidパラメータによって付加されるセッションを示す引数「SessionID=XXXXXX」が推測され悪意あるアクセスに晒されるという危険性が考えられます。
この危険性を回避するためにセッションIDが出力されるたびに値を新しいものに置き換えるPHP関数 session_regenerate_id()があります。
HTTP_Session2ではregenerateId()というメソッドでsession_regenerate_id()関数を呼び出せます。
このメソッドを使ってセッションIDを置き換えるメソッドをSession.class.php内にも実装します。
function Session(){ # 略 HTTP_Session2::regenerateId(true); }
セッションIDを置き換えるメソッドをコンストラクタに追加しています。
このようにすることでSession.class.phpが呼ばれるたびにセッションIDが新しいものに置き換えられます。
![index.php リロード時](http://cz-cdn.shoeisha.jp/static/images/article/5430/5430_link2.gif)
「トップ」リンクから再度index.phpにアクセスすると上記のようにセッションIDの値が前項のときの値と変わっているのが分かります。
regenerateId()メソッドを使用した後、ブラウザのバックボタンで戻った際、画面を更新する際にセッションが切れてしまうことがあります。
ブラウザの「進む」「戻る」での動作が多いと想定されるサイトや更新ボタンでの画面確認が多いサイトでは利用を避けたほうがいいです。
また、外部へセッションIDが漏れないようにするため会員制サイトから直接外部サイトへリンクしない、リンクする際にはリファラを送出しないページを挟む、といった対策が必要となります。
ユーザー情報変更
ユーザー情報変更はproofile.php内でSession.class.phpのupdateメソッドを呼び出して行います。
POSTされたuser_id, 旧・新password, user_nameを渡してDB更新後、セッションも更新します。
// id取得 $user_id = $_POST['user_id']; // 旧パスワード取得 $old_password = $_POST['old_password']; // 新パスワード取得 $new_password = $_POST['new_password']; // user_name取得 $user_name = $_POST['user_name']; // セッションクラス $ss = & new Session(); if($user_id && $old_password && $new_password && $user_name){ $ss->update($user_id, $old_password, $new_password, $user_name); }
function update($user_id, $old_password, $new_password, $user_name){ $pdo = new PDO(dbType.":host=".MYSQL_HOST."; dbname=".MYSQL_DATABASE , MYSQL_USER, MYSQL_PASSWORD); // user_id, 旧パスワードでチェック $stmt = $pdo->prepare("SELECT id, user_id, user_name, uid FROM user where user_id = ? AND password = ?"); $old_password = md5(str . $old_password); $stmt->execute(array($user_id, $old_password)); $rowCount = $stmt->rowCount(); if(!$rowCount) return false; // セッションからデータを取得 $_userInfo = $this->getSession(); // データ更新 $stmt = $pdo->prepare("UPDATE user SET user_id = ?, password = ?, user_name = ? WHERE id = ?"); $new_password = md5(str . $new_password); $stmt->execute(array($user_id, $new_password, $user_name, $_userInfo['id'])); // 更新後のデータを再度セッションに置く $stmt = $pdo->prepare("SELECT id, user_id, user_name, uid FROM user where id = ?"); $stmt->execute(array($_userInfo['id'])); $row = $stmt->fetch(PDO::FETCH_ASSOC); HTTP_Session2::set('user', $row); }
updateメソッド内でセッション内のユーザーデータを更新しておくことで、次回以降ユーザーデータを参照する際にはDBまで見に行かずセッションを参照するだけでよいことになります。