YUI2.7.0+PHP5でログアウトの処理を作る。

前回(YUI2.7.0+PHP5でログインの処理を作る)の自然の流れとして、Logout処理を作ってみた。

Javascriptから、XHRでPHPのプログラムを呼び出して以下の処理を行う。

  • SESSIONに紐づいているCOOKIEの廃棄
  • SESSION内に保管してデータの削除

また、これを確認するために、サーバー上のセッションの状況を調べる処理も実装した。

以下が初期画面のスナップショット。test sessionとあるボタンで、セッションの状態を調べる。


以下はdummy@dummy.comでログイン後のスクリーンショット。今回のサンプルでは、ログイン時にSESSIONにEmailアドレスを保管して、それをログイン後の画面に表示するようにした。


以下は、ログイン後にtest sessionボタンを押したときのスクリーンショット。画面下部に、Sessin ID(Session name)と、それに紐づいてサーバーに保管されているEmailアドレスを表示している。


以下はログアウト後にtest sessionボタンを押したときのスクリーンショット。画面下部に、Session IDが設定されていないこと、Emailアドレスも保管されていないこと、が示される。


以下にプログラムを示す。
まず、はじめは改定したLoginプログラム(login1.php)。このログインが成功した際に、SESSIONに(ユーザーを検索するためのキーになる)Emailアドレスを保管する。

<?php
/* 
 * ログインダイアログからのajax送信を受け取る。
 *  ログインOKの場合、セッションを作成して、Emailアドレスを戻す。
 *      
 *		author	; t.odaka
 *		date	; 2009/5/7
*/
	
	require_once("LoginTextDao.class.php");
	require_once("../Myznala/MyConverter.class.php");
	
	// リクエストデータの取り出し
	switch($_SERVER['REQUEST_METHOD']) {
		case 'GET'	: $rMethod = &$_GET; break;
		case 'POST'	: $rMethod = &$_POST; break;
		default:
	}

	// パラメータをサニタイズして配列に入れる。
	$cObj = new MyConverter();
	$reqParm = array();
	foreach ($rMethod as $key => $value) {
		$key	=$cObj->sanitize($key,'UTF-8');
		$value	=$cObj->sanitize($value,'UTF-8');
		$m_log->debug($key.'; '.$value); // Debugログ
		$reqParm[$key]=$value;
	}
	
	// データの更新と削除
	$pObj = new LoginTextDao();
	$pObj->setFileName('data/users.txt');
	// users.txtをopen.
	$fp = $pObj->fileOpen('r');
	
	$ret;
	$retObj = $pObj->findByUniqueKey($fp, $reqParm['auth1']);
	// ユーザーの存在証明
	if($retObj == null){
		$ret = 'ユーザーとパスワードが一致しません.';
	// パスワードの一致証明
	}else if($retObj->getPassword() != $reqParm['auth2']){
		$ret = 'ユーザーとパスワードが一致しません.';
	}else{
		/*
	 	* セッションオブジェクトの生成
	 	*/ 
		// セッションの開始
		session_start();
		$_SESSION['Email']=$retObj->getEmail();
		$ret = $retObj->getEmail();
	}
	
	// users.txtをclose.
	$pObj->fileClose($fp,'r');
	
	
	// 出力
	header("Content-Type:text/html");
	echo($ret);
	
	return;
?>


次は、Logoutを行うPHPプログラム(logout1.php)。Cookieの廃棄とセッションに格納されているEmailアドレスを削除する。

<?php
/* 
 * ログアウトを行う
 *  login1.phpで作成したセッションの削除を行う。
 *      
 *		author	; t.odaka
 *		date	; 2009/5/7
*/
	
	// セッションの開始
	session_start();
	if (isset($_COOKIE[session_name()])) {
		$m_log->debug('$_COOKIE[session_name()]: '.$_COOKIE[session_name()]); // Debugログ
		setcookie(session_name(), '', time()-42000, '/');
	}
	unset($_SESSION['Email']);

	return;
?>


次は、test sessionが押された際に呼び出されるPHPプログラム(logout_test1.php)。注記にあるように、この中でセッションスタートを行うので、ログアウト後(セッション破棄後)にこれを呼び出すとSession IDが新たに付与される。

<?php
/* 
 * セッションID、セッション内のデータの確認を行う。
 *      
 *		author	; t.odaka
 *		date	; 2009/5/7
*/

	$ret;
	// (注記)
	// セッションを開始しないと$_SESSION['Email']にアクセスできないので
	// ログアウト後でも、このプログラムにアクセスするとSession idが発行
	// される。
	session_start();
	
	if (isset($_COOKIE[session_name()])) {
		$ret='session_name: '.$_COOKIE[session_name()];
	}else{
		$ret='セッション用クッキーは保存されていません.';
	}
	
	// ログインの有無は、以下の結果で判定するのがいいだろうなぁ。
	if(isset($_SESSION['Email'])) {
		$ret.='<br>Email: '.$_SESSION['Email'];
	}else{
		$ret.='<br>Emailアドレスは保存されていません.';
	}
	
	// 出力
	header("Content-Type:text/html");
	echo($ret);
	
	return;
?>


最後にJavascriptを含むHTMLの全文を示す。login1.phpからの戻り値は

ログイン成功時 EMailアドレス
ログイン失敗時 エラーメッセージ

となっている。戻り値がEmailアドレスかどうかの判定に、以前作成した、MyValidatorを利用した。

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html> 
<head> 
	<meta http-equiv="Pragma" content="no-cache">
	<meta http-equiv="Cache-Control" content="no-cache">
	<meta http-equiv="Expires" content="Thu, 01 Dec 1994 16:00:00 GMT">
	<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
	<meta http-equiv="Content-Style-Type" content="text/css">
	<meta http-equiv="Content-Script-Type" content="text/javascript">
<title>Login</title> 
 
<style type="text/css"> 
</style> 

<link rel="stylesheet" type="text/css" href="../scripts/lib/yui/build/fonts/fonts-min.css" /> 
<link rel="stylesheet" type="text/css" href="../scripts/lib/yui/build/container/assets/skins/sam/container.css" /> 

<script type="text/javascript" src="../scripts/lib/yui/build/yahoo-dom-event/yahoo-dom-event.js"></script> 
<script type="text/javascript" src="../scripts/lib/yui/build/container/container.js"></script> 
<script type="text/javascript" src="../scripts/lib/yui/build/connection/connection-min.js" ></script>

<!--// MyValidatorの読み込み -->
<script type="text/javascript" src="../scripts/myznala.js">
</script> 
<style type="text/css" id="defaultstyle">
#main {
	margin: 2px;
	padding: 3px;
}

.ez_error {
	/* red(エラー用) */
	color:#ff0000;
}

</style>

<script type="text/javascript">

ModalLogin = function() {
	var valObj;
	
	var Event	= YAHOO.util.Event;
	var Dom		= YAHOO.util.Dom;
	
	var loginPanel;

	/*
	* ログインダイアログでキャンセルボタンをクリックした時のハンドラ
	*/
	var calselClickHdlr = function(){
		// ダイアログを消す
	        loginPanel.hide();
     	        Dom.setStyle("logindialog","visibility","hidden");
		// エラーメッセージのクリア
		Dom.get('msg').innerHTML = '';
	}

	/*
	* ログインダイアログでログインボタンをクリックした時のハンドラ
	*/
	var loginClickHdlr = function(){
		// エラーメッセージのクリア
		Dom.get('msg').innerHTML = '';

		var _url	= 'login1.php';
		var _parm 	= 'auth1=' + Dom.get('auth1').value + 
							'&' + 'auth2=' + Dom.get('auth2').value;
		// 戻ってきたときのために、メッセージ表示用エレメントのidをセットする。
		var _arg ={
			'resId'	: 'msg'
		};
		loginCallback.argument = _arg;
		// ajaxで検証
		YAHOO.util.Connect.asyncRequest('POST',_url,
						loginCallback, _parm);
	}

	/*
	* Login/Logoutのリンクをクリックした時のハンドラ
	*/
	var clickHdlr = function(_evt){
		Event.preventDefault(_evt);
		// id=loginはトグルにする
		if(Dom.hasClass('login','my_logout')){
			loginHdlr(_evt);
		}else{
			logoutHdlr(_evt);
		}
	}
	
	/*
	* Login時のハンドラ
	*/
	var loginHdlr = function(_evt){

		Dom.get('msg').innerHTML = '';
		Dom.get('res').innerHTML = '';
		Dom.get('test_res').innerHTML = '';     
		Dom.get('auth1').value = '';
		Dom.get('auth2').value = '';

    	// Panelオブジェクトは、ページスコープで一回だけ生成する。
        if (!loginPanel) {

			// ログイン用のモーダルパネルを生成する。
        	loginPanel = new YAHOO.widget.Panel("loginpannel",  
				{ 
                            	fixedcenter: true, 
                            	close: false, 
                             	draggable: false, 
				// 一番上に出す。
                            	zindex:4,
				// Modal指定。
                            	modal: true,
				// showされるまでは見えない。
                       		visible: false
            			} 
        	);

		// loginDialogを定義する
        	loginPanel.setHeader("Login");
        	loginPanel.setBody(Dom.get("logindialog"));
        	loginPanel.render(document.body);
		}

        // ログインダイアログの表示
       	Dom.setStyle("logindialog","visibility","visible");
        loginPanel.show();
        
	};
	
	/*
	* Login時のコールバック
	*/
	var loginCallback = {
    	        success : function(_obj) {
			var _resId = _obj.argument.resId;
			// XHRの戻り値の取得(エラーメッセージ)
			var _ret = _obj.responseText;

			// 戻り値がE-Mailアドレスかどうか検証
			var _wkRet = valObj.validate('ja','isEmail',_ret);

			//alert(_wkRet['isEmail'].length);
			// エラー時の処理
			if('isEmail' in _wkRet){
				// エラーのハンドル(皆さん適当に)
				// エラーが複数のときは複数行にして表示する。
				if(Dom.get(_resId).innerHTML.length > 0){
					Dom.get(_resId).innerHTML += ' &nbsp ' +_ret;
				}else{
					Dom.get(_resId).innerHTML = _ret;
				}
			}else{
				// ログイン成功
				loginPanel.hide();
		     	Dom.setStyle("logindialog","visibility","hidden");
				// エラーメッセージのクリア
				Dom.get('msg').innerHTML = '';
				// Logoutを表示
				Dom.removeClass('login','my_logout');
				Dom.addClass('login','my_login');
				Dom.get('login').innerHTML = "Logout";
				Dom.get('loginname').innerHTML = _ret;
			}
		},
		
     	        failure : function(_obj) {
 			var _resId = _obj.argument.resId;

 			var _ret = 'ステータス: ' + _obj.status + 'ステータステキスト: ' +
 						_obj.statusText + '読み込みに失敗しました。';
 			// エラーのハンドル(皆さん適当に)
 			Dom.get(_resId).innerHTML = _ret;	     
 		}
	 };

	/*
	* Logout時のハンドラ
	*/
	var logoutHdlr = function(){
		// Loginを表示
		Dom.removeClass('login','my_login');
		Dom.addClass('login','my_logout');
		Dom.get('login').innerHTML = "Login";
		Dom.get('loginname').innerHTML = '';
		// エラーメッセージのクリア
		Dom.get('msg').innerHTML = '';
		Dom.get('test_res').innerHTML = '';     

		// session削除のためのajax
		var _url	= 'logout1.php';
		// ajaxで検証
		YAHOO.util.Connect.asyncRequest('POST',_url,
						logoutCallback);
		
	}

	/*
	* Logout時のコールバック
	*/
	var logoutCallback = {
	    	success : function(_obj) {},
	     	failure : function(_obj) {
	 		var _ret = 'ステータス: ' + _obj.status + 'ステータステキスト: ' +
	 			'Logoutに失敗しました';
	 		// エラーのハンドル(皆さん適当に)
	 		Dom.get('res').innerHTML = _ret;	     
		}
	 };

	/*
	* test sessionボタンを押したときのハンドラ
	*/
	var testHdlr = function(){
		Dom.get('test_res').innerHTML = '';     

		// session testのためのajax
		var _url	= 'logout_test1.php';
		// ajaxで検証
		YAHOO.util.Connect.asyncRequest('POST',_url,
						testCallback);
		
	};

	/*
	* test sessionボタンを押したときのコールバック
	*/
	var testCallback = {
	    	success : function(_obj) {
			// XHRの戻り値の取得(エラーメッセージ)
			var _ret = _obj.responseText;
			Dom.get('test_res').innerHTML=_ret;
		},
	     	failure : function(_obj) {
			var _ret = 'ステータス: ' + _obj.status + 'ステータステキスト: ' +
					'Testに失敗しました';
			// エラーのハンドル(皆さん適当に)
			Dom.addClass('test_res','ez_error');
			Dom.get('test_res').innerHTML = _ret;     
		}
	};
	
	return{
    	init: function() {

		// ログインダイアログを表示するハンドラー
	        Event.on("login", 
	        	"click", 
	        	clickHdlr);

	        // ダイアログ内のLoginボタンのハンドラー
	        Event.on("loginbutton", 
        		"click", 
        		loginClickHdlr);
	        
		// ダイアログ内のCanselボタンのハンドラー
	        Event.on("canselbutton", 
        		"click", 
        		calselClickHdlr);

		// test sessionのハンドラー
	        Event.on("test", 
    	        	"click", 
    	        	testHdlr);

    		// 検証オブジェクトの初期化
			valObj 	= 	new MyValidator();
        	
		}
	};
}();

//DOMが完全にloadされたら、サンプルを初期化する。
YAHOO.util.Event.onDOMReady(
	//DomReadyイベントで発火するハンドラ
	ModalLogin.init,
	//ハンドラに渡すオブジェクト
	ModalLogin,
	//ハンドラは、上記のオブジェクトのスコープをもつ。   
	true
);

</script>
</HEAD>

<BODY class="yui-skin-sam">
test_login2.html
<br>
<div id="container">
<p>
Login/Logoutのサンプルです。<br/>
test sessionボタンで、session idとsession内のEmailアドレスが確認できます。
</p>
<a id="login" href="#" class="my_logout">Login</a> &nbsp <div id="loginname"></div>
<div id="res" class="ez_error"></div>

<br>
<form action="#">
<input id="test" type="button" value="test session">
</form>
<div id="test_res"></div>


<div id="logindialog">
	<form action="#">
		<table border="0">
		<tr><td>E-Mail</td>
			<td><input id="auth1" type="text" size="30"></td></tr>
		<tr><td>Password</td>
			<td><input id="auth2" type="password" size="30"></td></tr>
		<tr><td colspan="2">
			<input id="loginbutton" type="button" value="Login"> &nbsp
			<input id="canselbutton" type="button" value="Cansel">
		</td></tr>
		</table>

	</form>
	<div id="msg" class="ez_error"></div>
	<a HREF="mailto:dummy@dummy.com">パスワードを忘れた場合には。</a>
</div>

</div>
</BODY>
</HTML>