3流プログラマのメモ書き

元開発職→社内SE→派遣で営業支援の三流プログラマのIT技術メモ書き。 このメモが忘れっぽい自分とググってきた技術者の役に立ってくれれば幸いです。(jehupc.exblog.jpから移転中)

PHPで携帯電話でもセッションが使えるようにする

(CakePHP)携帯電話でもセッションを使えるようにするでも書いたように、携帯電話向の場合、セッションIDの扱いに気を使う必要があります。

(まぁドコモがcookie使えないのが諸悪の根源なんですが。。。)

【PHPで作る】初めての携帯サイト構築:第5回 携帯サイトでセッションを取り扱う|gihyo.jpによると、session_start();より前に下記を指定すればいいとあります。

ini_set('session.use_cookies', 0);

ini_set('session.use_only_cookies', 0);

ini_set('session.use_trans_sid', 1);

これで、aタグのリンクやフォームの送信先に自動的にセッションIDがつくはず なんですが。。。

どうもつきません。

どうやら、session.use_trans_sid の設定は、PHP マニュアル:ini_set をみると、PHP_INI_SYSTEM|PHP_INI_PERDIR となっています。

つまり、.htaccess か、php.ini または httpd.conf での設定のみ有効で、ユーザソース内には埋め込めないということですね。

本来は、.htaccess で設定するのがいいんでしょうが、今回のスクリプトは複数のレンタルサーバで動かす予定、借りてるレンタルサーバの一部が特殊で簡単にはできません。

レンタルサーバ毎にphpの挙動を変えるのもあれなので、ユーザスクリプト内で解決することにしました。

(といってもやってる仕組自体は、(CakePHP)携帯電話でもセッションを使えるようにする と同じですが。。)

まず、アクセスしてきたのがケータイなら、session_start() より前にクッキーを使わないように指定します。

アクセスしてきた端末が携帯かどうかの判定は (PHP)携帯のキャリア振り分け方法 で書いたように Net_UserAgent_Mobile という PEAR ライブラリを使うと楽なんですが、PEARも入れることができない状態なので手動で UserAgent から判断します。

(PHP)セッションと認証の仕掛け にあるソースをベースにして携帯対応した感じを下記に書いてみます。

●index.php

require_once 'util.php' ;

//初期処理

Init();

//ユーザ情報

$username = "user";

$passwd = "41d3f22b449c345290adaa3ad7380d3c6";//パスワードのハッシュ

//メッセージ

$txtMsg ="";

if ( ! array_key_exists('userid', $_POST) && ! array_key_exists('passwd', $_POST) ){

//入力データが無いなら初回ログインとみなし、何も表示しない

$txtMsg ="";

}else if( $username == $_POST['userid'] && $passwd == md5( $_POST['passwd']) )

{

//認証成功

//セッション開始

session_start();

//セッションにユーザ名入れる。(他のページではusernameセッション変数があれば認証OKとする)

$_SESSION["username"] = $username;

//会員ページへ遷移

$sid = session_id();

if ( MobileCheck() ){

//携帯ならセッションIDを付ける

header("Location:input.php?PHPSESSID=" .$sid);

}else{

header("Location:input.php");

}

exit;

}else{

//認証失敗時のメッセージ

$txtMsg =" 入力したログイン情報に誤りがあります。正しい値を入力してください。

";

}

//Smarty読み込み(ドキュメントルート外のSmartyクラスにアクセス)

require_once('../smarty/libs/Smarty.class.php');

//Smartyオブジェクト作成

$smarty = new Smarty();

//Smartyディレクトリ設定(キャッシュやテンプレート置き場など)

$smarty->template_dir = "../smarty/templates";

$smarty->compile_dir = "../smarty/templates_c";

$smarty->cache_dir ="../smarty/cache";

//表示データをアサイ

$smarty->assign("txtMsg", $txtMsg);

//テンプレート表示

$smarty->display("index.tpl");

?>

●index.tpl

http-equiv="Content-Type" content="text/html; charset=UTF-8">

</span></a></span>ログイン<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">

ログイン

{* ログインメッセージ *}

{$txtMsg}

method="post" action="index.php" id="login">

ユーザ名: type="text" style="ime-mode: disabled" maxlength="10" name="userid" id="userid">

パスワード: type="password" style="ime-mode: disabled" maxlength="10" name="passwd" id="passwd">

type="submit" value="ログイン" class="submitstyle" name="Submit">

●util.php

/**

* 初期化処理。文字コードの設定。各ページの最初に呼ぶこと。

*/

function Init(){

//ケータイの場合はcookieを使わない。

if( MobileCheck() ) {

ini_set('session.use_cookies', 0);

ini_set('session.use_only_cookies', 0);

}

header("Content-type: text/html; charset=UTF-8");

mb_language("Japanese");

mb_internal_encoding("UTF-8");

}

/**

* ログインしているかのチェックを行う。 セッションも開始する。

* ログインしていなければログインページに飛ばす。

*/

function LoginCheck(){

session_start();

//認証できてなければログインページへ

if ( ! isset( $_SESSION["username"] ) ){

header("Location:index.php");

exit;

}

}

/**

* ユーザエージェントをみて携帯かどうか判断。

* t:携帯 f:携帯でない

*/

function MobileCheck(){

//ケータイの場合はURLにセッションIDを持たす

$agent = $_SERVER['HTTP_USER_AGENT'];

if(preg_match("/^DoCoMo/i", $agent) ||

preg_match("/^(J\-PHONE|Vodafone|MOT\-[CV]|SoftBank)/i", $agent) ||

preg_match("/^KDDI\-/i", $agent) || preg_match("/UP\.Browser/i", $agent) ){

return true;

}

return false;

}

?>

●認証が必要な入力ページ(認証失敗ならログイン画面に遷移)

require_once 'util.php';

//初期処理

Init();

//ログインチェック

LoginCheck();

//処理.....

//Smarty読み込み(ドキュメントルート外のSmartyクラスにアクセス)

require_once('../smarty/libs/Smarty.class.php');

//Smartyオブジェクト作成

$smarty = new Smarty();

//Smartyのディレクトリ設定(キャッシュやテンプレート置き場など)

$smarty->template_dir = "../smarty/templates";

$smarty->compile_dir = "../smarty/templates_c";

$smarty->cache_dir ="../smarty/cache";

//携帯ならセッションIDを付加

$sid = null;

if(MobileCheck()){

$sid = session_id();

}

$smarty->assign("sid", $sid);

//表示データをアサイン

$smarty->assign("test", $test);

//テンプレート表示

$smarty->display("input.tpl");

?>

●input.tpl

href="test.php{if isset($sid)}?PHPSESSID={$sid}{/if}">テスト

method="post" action="confirm.php{if isset($sid)}?PHPSESSID={$sid}{/if}" id="input">

type="hidden" name="enc" value="あ">

type="text" name="aa" value="">

type="submit" value="送信" name="submit">

ポイントは携帯電話からのアクセスと分かった場合のみ、session.use_cookies と session.use_only_cookies でクッキーを無効にし、フォームやサイト内のセッションが必要となるページのみセッションID(PHPSESSID=xxxx)を付け加えることです。

今回はSmartyを使ったので、テンプレート変数 $sid に携帯からのアクセスならセッションIDを入れて、テンプレート内でif文で表示するかどうか判断することとしました。

あまりきれいな方法ではないですが、こうすることでドコモの携帯でもセッションを使えます。

ただし、URLにセッション情報を埋め込むのはセキュリティ的リスクが高いので注意しましょう。

参考:

ini_setに制限があるのでしょうか?

【php&ethnaで携帯サイトを作る】セッション管理(前編)

PHPプログラムメモ | 携帯サイト|プログラムメモ

PC+携帯サイトを同一URLで運営する時のsession.use_trans_sid - チラシの裏 - Yahoo!ブログ

PHPで携帯の各キャリアとPCの判別、振り分けをする OPQR.jp