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

2007/12/12 水曜日 matsui Posted in PHP, サーバ 23 Comments »

今回は、ケータイ上から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が変わるため、通信エラーが起こった際にセッションが切れてしまう可能性があるようです。
利便性を重視するかセキュリティを重視するか、扱う情報の重要度に応じて使い分けると良いと思います。
(詳しくはコメント欄をご参照ください)

 

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



「Google Chart API」をケータイから使ってみる
    このエントリをはてなブックマークに登録

2007/12/10 月曜日 matsui Posted in PHP 1 Comment »

先日公開されたばかりの「Google Chart API」を、ケータイから使ってみようと思います。

「Google Chart API」とは、グラフを描画するためのAPIで、パラメータを投げるとGoogle側でPNG画像としてグラフを生成してくれるものです。

参考サイト:
→ Google Chart API Developer’s Guide [google.com]
→ PHPSPOT開発日誌 Googleのグラフ描画API「Google Chart API」 [phpspot.org]
→ 404 Blog Not Fount Google Code Chart – 折れ線グラフうぃざ~ど [livedoor.jp]

しかしながら、DoCoMoの端末はPNG画像が表示できないため、コンバートしてやる必要があります。
au, ソフトバンクに関してはそのままで大丈夫です。

 

GoogleChartサンプルPHPコード

<?php
// チャートのURL
$url = 'http://chart.apis.google.com/chart';
$url .= '?cht=p3&chd=s:hW&chs=250x100&chl=ke-tai|org';

// ドコモの場合のみ
if (preg_match('/^DoCoMo/', $_SERVER['HTTP_USER_AGENT'])) {
	// 画像を取得
	$resource = imagecreatefrompng($url);

	// ヘッダを出力
	header('Content-type: image/gif');

	// PNG画像をGIFに変換してストリーム出力
	imagegif($resource);
} else {
	// 通常通りPNG画像で表示
	header('Location: ' . $url);
}
?>

 

そのまま上記のPHPにアクセスしても良いですし、

<img src="[上記のPHPファイル名]" />

というように、imgタグで読み込んでも大丈夫です。

なお、パラメータ「chs」で画像の幅と高さを指定できますので、ケータイに合わせて、控えめな数値を設定してやる必要があります。

また、image関数を使用していますので、動作させるには、PHPセットアップ時にGDを使えるようにしておく必要があります。

変換には少しだけ負荷がかかりますので、アクセスの多いサイトであれば、キャッシュする仕掛けを作成した方が良いかも知れません。

google_chart.jpg
ドコモ端末からグラフを表示



PHPで拡張子を出し分けし、携帯全機種で画像を表示する方法
    このエントリをはてなブックマークに登録

2007/12/6 木曜日 matsui Posted in PHP No Comments »

ケータイサイトを開発する上でやっかいな問題の一つに、キャリアや機種によって表示できない画像フォーマットがあるという点があります。

今回ご紹介するのは、機種によって画像の拡張子を置き換え、全ての端末で画像を正しく表示するためのPHPサンプルプログラムです。
あくまで拡張子を置換するだけですので、あらかじめ画像をアップロードする際に、「JPG」「GIF」「PNG」と3種類の画像を設置する必要があります。

 

ユーザエージェントで画像の拡張子を置換するサンプルプログラム

// 対象となる画像ファイル名をセット
$filename = 'testimage.jpg';

// 拡張子を取得
$ext = substr($filename, -4);

// ユーザエージェントの取得
$agent = $_SERVER['HTTP_USER_AGENT'];

if (preg_match('/^DoCoMo/', $agent)) {
	// DoCoMoの場合
	if ('.png' == $ext) {
		// 「.png」→「.gif」に置換
		$ext = '.gif';
	} elseif ('.jpg' == $ext) {
		$nglist = '501i|502i|821i|209i|651i|691i|671i|210i
|F503i|SO503i|D503i|F211i|D211i'; // ※実際には1行で入力
		$pattern = "/^DoCoMo\\/1\\.0\\/.*($nglist)/";
		if (preg_match($pattern, $agent)) {
			// 「.jpg」→「.gif」に置換
			$ext = '.gif';
		}
	}
} elseif (preg_match('/^J-PHONE/', $agent)) {
	// ソフトバンク3G以前の場合
	if ('.gif' == $ext) {
		// 「.gif」→「.png」に置換
		$ext = '.png';
	}
}

// 出力
echo substr($filename, 0, -4) . $ext;

※表示の都合上、改行をいれています

 

次のルールで置換を行っています。

  • ドコモはPNGを表示できないため「.gif」に置換
  • ドコモのJPG非対応機種は「.gif」に置換
  • ソフトバンクの3G以前の機種はGIFを表示できないため「.png」に置換

厳密な機種判定を行っているわけではないので、多少ルーズな処理ですが、ひとまずこれで「画像が表示されない」というケースは避けることができるはずです。

 

関連:



PHPを使ってたった2行で絵文字をエスケープする方法
    このエントリをはてなブックマークに登録

2007/12/3 月曜日 matsui Posted in PHP No Comments »

先日の「PHPを使ってたった2行で絵文字を取り除く方法」の応用技です。

SJIS形式の絵文字は、そのままだとDBに格納する際や文字コード変換時に、文字化けを起こしてしまうことがあります。

iモードの場合は、先日ご紹介した、
iモード絵文字をSJIS形式からUnicode形式に変換するPHPサンプル
の方法でもエスケープできますが、ドコモのみの方法ですし、やや面倒です。

今回はもっと簡単にエスケープする方法をご紹介します。
この方法であれば、DoCoMo・au・SoftBank(SJIS形式のみ)の絵文字は全てエスケープできますし、後で元に戻すこともできます。

 

エスケープ処理 サンプルコード

$str = '絵文字[晴れ]';
mb_substitute_character('long');
$str = mb_convert_encoding($str, 'SJIS', 'SJIS');

// 出力
echo $str;

※ソースはSJISで記述します
※Blog上では絵文字は表示できませんので、「晴れ」の部分は絵文字を入力し直してください。

実行例:
emoji_escape1.gif

 

mb_substitute_character」は、存在しない文字コードがある場合(いわゆるゲタになる場合)の処理を設定するためのものです。
「long」を指定すると、存在しない文字は「BAD+[SJISコード]」という文字列に置換されます。
次の「mb_convert_encoding」で実際に変換を行うと(ダミーのためSJIS→SJISでOK)、絵文字がエスケープされる仕掛けです。

 

変換後のデータを元に戻すサンプルは次の通りです。

逆エスケープ処理 サンプルコード

$str = '絵文字BAD+F89F';

// 絵文字を検索
$pattern = "/BAD\\+[0-9A-F]{4}/";
preg_match_all($pattern, $str, $arr); // $arr[0]に対象絵文字が格納される

// 絵文字に置換
$rep_arr = array();
foreach($arr[0] as $value) {
	$dec = hexdec(substr($value, 4, 4));
	$rep_arr[$value] = pack('n', $dec);
}

// 置換処理
$str = strtr($str, $rep_arr);

// 出力
echo $str;

実行例:
emoji_escape2.gif

 

関連:



PHPを使ってたった2行で絵文字を取り除く方法
    このエントリをはてなブックマークに登録

2007/11/28 水曜日 matsui Posted in PHP 2 Comments »

今回は、PHPで一番簡単と思われる、絵文字を取り除く方法をご紹介します。

iモードとau、およびソフトバンクのSJIS形式の絵文字を取り除くことができます。

サンプルコード

$str = '絵文字[晴れ]';

mb_substitute_character('none');
$str = mb_convert_encoding($str, 'SJIS', 'SJIS');

// 出力
echo $str;

※ソースはSJISで記述してください

 

これだけでOKです。
mb_substitute_character」は、存在しない文字コードがある場合(いわゆるゲタになる場合)の処理を設定をするためのものです。
ここで”none”と設定すると削除が行われます。
次の「mb_convert_encoding」で実際に変換を行うと(ダミーのためSJIS→SJISでOK)、絵文字が削除されます。

実行速度も早く、絵文字を取り除くには、この方法が決定版かもしれません。

emoji_cut_i.jpg
DocoMoは当然OK

emoji_cut_au.jpg
auもOK

emoji_cut_sb.jpg
SoftBankだってOK

 

なお、ソフトバンクにはSJIS形式以外にも、フォーム値を通常の絵文字形式で送信してくる端末も、数多くあります。
その場合は正規表現などで検出し、取り除く必要があります。
(上記のソフトバンク絵文字を削除するサンプルは、また後日アップします)

追記: 公開しました。こちらです。

この2つの方法を併用することで、全てのキャリア、全ての絵文字を削除することができそうです。

 

関連: