PHPでケータイからセッションを使う場合の設定方法
    このエントリをはてなブックマークに登録

今回は、ケータイ上からPHPのセッションを使う場合の設定方法についてです。

ケータイからPHPのセッションを機能を使う場合、端末によってはクッキーが利用できない場合があるため、そのままでは使うことができません。

セッションを使いたい場合は、インストール時のconfigureオプションに、「–enable-trans-sid」を付ける必要があります。
※Windowsの場合は特に設定の必要はありません。

また、「php.ini」の設定で、次のように設定してください。
※設定変更後はWebサーバの再起動が必要です

session.use_trans_sid = 1

もしくは「.htaccess」でも設定することができます。
※.htaccessでの設定上書きが許可されている場合のみ

php_flag session.use_trans_sid On

設定変更は、phpinfoで確認できます。

php_session01.gif

PHPのコード内で、

ini_set('session.use_trans_sid', '1');

でも設定できますが、その場合は「session_start();」より前に実行する必要があります。

 

設定が有効になると、リンクの後ろに自動でセッションIDが付加され、セッション変数が引き継げるようになります。
※ただしクッキーが使える端末で、「session.use_cookies On」の場合には、セッションの管理にはクッキーが優先して利用され、URLにセッションIDはつきません。

セッションIDが付加された例:

<a href="index.php?PHPSESSID=b37b5e8e31118c45e19a5fb6b70c215a">
トップへ
</a>

ページの移動に静的HTMLを挟んだり、引数をつけないでリダイレクトしたりすると、セッションは切れてしまいますので注意が必要です。

 

※セッションハイジャックに対する注意書きが足りないとのご指摘を受けましたので追記しました。失礼しました。

上記設定のままですと、URLに固定のセッションキーがついたままの状態のため、リンク先のページにRefererが漏れてしまったり、友達へメールでURLを転送した場合などに、セッションハイジャックされてしまう可能性があります。
そこで安全度を高めるために、次のような対応策を平行して行うと良いようです。

※再度ご指摘を頂きました。iモードの端末はRefererを出力しないので、その場合はRefererを原因としたセッションハイジャックは考慮しなくてもよいようです。

  1. クッキーを利用できる端末の場合は、そちらを利用する
  2. 端末IDによる認証+IPアドレス制限を行う
  3. session_regenerate_id関数を利用する

1については、auとソフトバンクの最近の機種ではクッキーが利用できます。
クッキーが利用できれば、URLにセッションIDを付加しなくてすみますので、URLからの漏洩を防ぐことができます。
セッションの管理にクッキーを優先して利用するには、「php.ini」または「.htaccess」で、「session.use_cookies On」と設定されている必要があります。

2の「端末IDによる認証+IPアドレス制限」については、まず.htaccessなどで、携帯キャリアのIPアドレスからのみアクセス可能な状態にします。
その状態でセッションに端末IDを格納し、アクセスの度に認証チェックを行うことでなりすましを防ぎます。
IPアドレスの制限をかけるのは、Refererが漏れている場合は、端末IDも同時に漏れているケースが多いためです。
端末IDはリクエストを偽造することで、なりすまされる可能性があるため、携帯実機からのアクセスのみとすることで安全度を高めます。

3の「session_regenerate_id関数」は、アクセスの度にセッションIDを変更するためのものです。
PHPのバージョンによって対処法が異なりますので注意が必要です。

まずPHP5の場合は簡単です。

PHP5でのセッションID再生成のサンプル

session_start();
session_regenerate_id(true);

session_regenerate_idの引数にtrueをセットすることで、古いセッションIDは破棄され、毎回新しいIDがふられます。

PHP4ではこの引数が利用できないため、古いセッションは破棄されず、同じことを実現しようとすると少し大変です。

PHP4でのセッションID再生成のサンプル

// セッション開始
session_start();

// 古いセッションを保存
$sess_tmp = $_SESSION;

// セッション変数を破棄
session_destroy();

// セッションIDを再生成
session_start();
session_regenerate_id();

// セッションを元に戻す
$_SESSION = $sess_tmp;

参考にさせて頂いたのはこちら[php.gr.jp]のページです。
欠点としては、アクセスの度にセッションファイルが作成されるため、ゴミファイルが残りやすいという点があります。

アクセスが多いサイトの場合は、ガーベージ・コレクションの設定をより頻繁にしたり、こちら[phppro.jp]こちら[ishinao.net]のやり方を参考にすると良いかも知れません。

なお、session_regenerate_id関数を使うと、毎回セッションIDが変わるため、通信エラーが起こった際にセッションが切れてしまう可能性があるようです。
利便性を重視するかセキュリティを重視するか、扱う情報の重要度に応じて使い分けると良いと思います。
(詳しくはコメント欄をご参照ください)

 

※追記分について、まだセキュリティ上問題があったり、何か他に良い方法がありましたら、ご指摘をお願いします


 

最近の記事







23 Responses to “PHPでケータイからセッションを使う場合の設定方法”

  1. session_regenerate_id()を毎回使うと携帯の通信不良で再リクエストした場合に、サーバー側でセッションIDが変わってしまっているという不具合が起こるのではないでしょうか?

  2. コメントありがとうございます。参考になります。
    確かにその通りですね。
    何か良い対応策をご存知ないでしょうか?

  3. 一般に携帯の場合session_regenerate_id()は使用できないと思います。

    またAUのproxyで同一リクエストを二回出す場合がなぜかあります。AUのproxyは要注意です。

  4. これ消しておいたほうがよくね?

  5. irokさん、またまたコメントありがとうございます。
    大変参考になり助かります。

    auとSoftBankの場合は、ほぼCookieが使えますし、端末IDの取得も容易なため、記事内の対応策1, 2の方法を使えば大丈夫そうですね。

    問題はDoCoMoの場合ですが、こちらは扱う情報の重要度によって、利便性とセキュリティのトレードオフになってしまうのかな、と思っています。

    対策案として次のようなものを考えてみました。

    (1) 気にせずsession_regenerate_id()を使う。通信エラーが出た場合はやりなおしてもらう。(1番セキュア?)
    (2) 毎ページ端末IDを送信してもらう(同じくセキュアだが毎回ダイアログが出るため現実的ではない)
    (3) セッションの時間を短くして多少安全度を上げる(気休め程度の効果?)
    (4) セッションにユーザエージェントを持ち、アクセス毎に照合する(IPアドレス制限との併用でそこそこの効果?リファラが漏れている場合は、同時にUAも漏れているため完璧ではない。)

    重要な個人情報を扱う場合は、多少利便性を低下させても(1)の方式を取らざるを得ないのかなと思っています。いかがでしょうか?

    せっかくの機会ですので、ここで最良と思われる方法を見つけ出したいと思っています。
    ノウハウをご存知の方がいましたらぜひコメントをお願いします。

    ※記事内にも注意書きを追加しました

  6. 携帯でのsessionは始めるまで結構苦労しました。

    いくつか気になったので…

    >設定が有効になると、リンクの後ろに自動でセッションIDが付加され、セッション変数が引き継げるようになります。
    設定次第でしょうが、クッキーが使えない環境の時に限り…とできます。
    その場合auやSBでは特に何も気にせずPCと同様session使えます。
    (URLにSIDが透過的に付加されません。)

    >リンク先のページにRefererが漏れてしまったり
    URLに埋め込みが必要なのは、実際i-modeのみでしょう。
    それでいて、i-modeはリファラーを吐きません。
    結局、上記のような状況にはならないのでは???

    それでも気になるなら、画面遷移にaタグは全て使わず、postにすればよい。
    この場合もPHPが勝手にhidden要素を付け加えてくれるから、URLはキレイ
    なままsessionは保たれます。

    たしかにセッションハイジャックって行われたら恐ろしい事でしょうが、クッキーならOKでURLに埋め込むとダメっていうのは、携帯の事情を知らなすぎるのではないでしょうか?
    (>指摘された方)

  7. Gekikawa様

    コメントありがとうございます。
    大変わかりやすい説明で参考になりました。

    これで一定の結論が出た気がします。
    3キャリア実機で動作を確認した後、適切と思われる形に記事を修正・追記しようと思います。
    もしよろしければ、後ほどまたご確認をお願いいたします。
    ありがとうございました。

  8. 再度記事を修正・追記しました。

  9. 携帯ユーザ Says:

    いつも拝見させてもらっています。
    少し気になったのでコメントします。
    携帯でのセッションを使う場合ですが、メールでURLを他人に教えてしまった時に問題が発生するのではないかと思います。
    AUやsoftbankでは問題ないとしても、i-modeの場合、URLの後ろにsidを付けている状態ですので、リスクがあります。

    他人にメールでURLを送信後、本人が一度もそのサイトにアクセスせずに、URLを受信した他人がアクセスしてしまった場合、session_regenerate_id()されるので、本人はアクセスできなくなるのではないでしょうか。(再びセッションを作成する処理をしない限り->端末IDを送信する必要がある)
    またその間になんらかの操作が行われた場合、なりすましも可能です。

    mixiなどのサイトではどういう処理で簡単ログインさせているのでしょうか。
    docomoの実機がないので検証できません。AU&softbankではURLにsidが埋め込まれていないので、cookieを使っているようです。

  10. 携帯ユーザさん

    コメントありがとうございます。
    セッション入りのURLを他人に教えてしまった場合、確かにセキュリティ上の問題がありますね。
    ドコモ端末では、session_regenerate_idを使わない限り、これは避けられないと思います。
    (他人に教えた時点で自己責任という面もありますが。。。)

    ただ、

    > 他人にメールでURLを送信後、本人が一度もそのサイトに
    > アクセスせずに、URLを受信した他人がアクセスしてしまった
    > 場合、session_regenerate_id()されるので、
    > 本人はアクセスできなくなるのではないでしょうか。

    こちらはあり得ません。
    なぜなら本人が一度アクセスしないと新しいセッションIDがわからないため、他人に教えることができないからです。

    > mixiなどのサイトではどういう処理で簡単ログインさせているのでしょうか。

    mixiで確認してみたところ、やはりURLの後ろにセッションIDが付加されているようです。
    ですが、session_regenerate_id()は使用していないようで、アクセス毎にセッションIDが変わることはないようです。

    ただ、3/31からドコモでもiモードIDが取れるようになるようですので、こちらを使うことで、この辺りの問題を一気に解消できそうな感じです。

  11. 携帯ユーザ Says:

    お返事ありがとうございます。

    >こちらはあり得ません。
    >なぜなら本人が一度アクセスしないと新しいセッションIDがわからないた>め、他人に教えることができないからです。

    メールでURLを他人に送信する際に、一度アクセスすると思います。
    その後、他人がそのURLでアクセスしてもドコモの場合は、端末IDなどで本人かどうか調べることはできないから、素通りできてしまいます。
    その時、PHP内部でsession_regenerate_id()が作動してしまい、セッションIDが変わります。
    他人がアクセスした後、本人がアクセスしようとしたら、セッションIDが変わっているため、さきほどのURLでは認証失敗ということになるのではないでしょうか?
    間違っていたらすいません。

    3/31が待ち遠しいですね!

  12. 携帯ユーザさん

    度々コメントありがとうございます。

    > メールでURLを他人に送信する際に、
    > 一度アクセスすると思います。
    > その後、他人がそのURLでアクセスしてもドコモの場合は、
    > 端末IDなどで本人かどうか調べることはできないから、
    > 素通りできてしまいます。

    もしおっしゃることを正しく理解していなかったらすいません。

    メールで他人にURLを送ったとしても、それは既にsession_regenerate_id()が動いた後のURL(古いセッションIDが記述されたURL)のため、送られた側の人はセッションを引き継げないと思ったのです。
    PCのようにHTMLソースを見て、リンク等から新しいセッションIDを知ることができ、それを他人にメール出来ていれば別ですが。

    どちらにしても、セッション情報を含んだアドレスを他人に教えるというその行為自体が一番の問題なのかもしれないですけどね。

  13. 一定の結論が出ているところに恐縮ですが、セッションID入りのURLについて

    > メールでURLを他人に送信する際…
    なぜそんなことをするのか?
    サイトへのログイン認証時のURLなんてだれも他人に教えないでしょう?
    って思っていましたが、メールでURLを送信と言うのは
    いわゆる「お友達におしえる」っていう行為なんですね。

    つまりユーザの多く(大多数?)はセッション入りのURLだろうと何だろうと
    面白いと感じたサイトのURLはすぐ、そのままメールするようですね。
    それが認証通過後のサイトコンテンツページのURLならば、なおさら
    危機感を感じる事はないのでしょう。
    (若年女性中心のサイトを運営している為かも知れませんが、最近↑を
    教えてくれるような事例に出会いました。)

    私が知る範囲ですが、現状ではお小遣いポイントサイトやHPスペース
    などでは一律URLにセッションIDを付加して、IDを変化させると言う事は
    していないと思います。
    まぁジャンルがジャンルだけにそれで良いのかもしれませんが。

    話を戻して、「アドレスを他人に教える」場合ですが、DoCoMoだと
    ブラウザ側の操作でそのようなメールが簡単に作成できるのですね。
    (だからそれが問題になるのでしょうが)
    auだとブックマーク先のURLをmetaタグで指定できるのですが、
    そういったことが可能であればなぁと思いました。

  14. Gekikawa様

    いつもコメントありがとうございます。そしてご返信が遅れて申し訳ありません。
    なるほど納得です。私の視点はシステム屋としてのもので、一般の方にとっては意識せず友達に教えてしまうものなのですね。そうかもしれません。
    metaタグの件もありがとうございます。勉強になります。
    この件もそうですが、キャリア間で規格を統一して欲しいですね。
    ドコモがクッキーに対応してくれれば、これらの問題は万事解決なんですが。

  15. ちょっと前の記事なのにコメントすいません。

    au,SoftBankでCookieを使用したセッションをする場合に
    SSLをまたぐと問題が出てきます。
    根本的な解決方法は思い浮かばないのですが。。

    http://d.hatena.ne.jp/maru_cc/20080512/au_ssl_cookie
    http://d.hatena.ne.jp/maru_cc/20080512/mobile_ssl_cookie

  16. maru_ccさん

    拝見させていただきました。
    大変参考になるコメントありがとうございます。

    auの場合が大変そうですね。
    クッキーベースをやめることで対応はできそうですが。。。

    結局セッションIDをURLをつけるのってどうなの?という話に回帰してしまいますね。

  17. […] 本はcookieのみ仕様可能な設定にしておく。携帯に対応する場合は下記ページのコメント欄が参考になりそう。 ke-tai.org > Blog Archive > PHPでケータイからセッションを使う場合の設定方法 […]

  18. health insurance tonik tonik insurance health

  19. 古い記事ですが、結論が出ていないようなのでコメントさせていただきます。

    一意なユーザーIDが取れるなら、外部にセッションを出す必要はありません。

  20. >一意なユーザーIDが取れるなら、外部にセッションを出す必要はありません。
    単にユーザの情報を引き回すだけがセッションを利用する目的ではありません。
    DBの負荷軽減という名目があります。

    ユーザ情報を取得するにはDBにアクセスしなければなりませんし、ログイン処理があるのであれば、ログイン済チェックを毎ページ行わなければなりません。

    規模が小さいと気になりませんが、ある程度大きくなってくると影響が出てきます。

    —-
    auとsoftbankはcookieを利用するということですが、3GC端末であれど、一部機種で利用できなかったりします。

    突き詰めて考えると、古い機種やイレギュラーな機種などの対応などを含めて、3キャリアともURLにsessionidを乗せるのが上策かと思います。

    セキュリティ面では以下の様にして高めることは可能です。

    ・IP制限を行う
    ・セッション内のUIDと、アクセスしているUIDでの認証
    ・UIDが取得できない場合は「ごめんなさい」

    携帯の場合、ブラウザバックが当たり前ですので、session_regenerate_id()は常用しておりません。

  21. >DBの負荷軽減という名目があります。
    これ前から気になっているのですが、
    実際どうなんでしょう?
    セッション関数使ってユーザー情報取得するのと、
    DBからUIDでユーザー情報取ってくるのと、
    負荷と速度に大きな違いがあるのでしょうか?

    どの程度の規模だとどのぐらいの規模なのでしょうか?

  22. >負荷と速度に大きな違いがあるのでしょうか?
    webサーバとDBサーバーを別ハードにて運用している場合、
    DBサーバーとWEBサーバーで通信が発生します。

    通信が発生するということは、
    DBとのセッションを毎回確立する必要があります。
    (Webサーバーの機能でDBセッションを保持することも可能ですが)

    サイトへの同時接続数にもよると思いますが、
    すべてのページでDBにアクセスするのは、コストがかかり過ぎると思います。
    インフラに投資できるプロジェクトであればさほど気にすることでもないかもしれませんが。

  23. […] 使う場合は、古いセッション情報を明示的に削除する必要がある。 PHPでケータイからセッションを使う場合の設定方法 // セッション開始 session_start(); // 古いセッションを保存 $sess_tmp = […]

コメントを書く