小金井にあるWEB制作会社の備忘録

MEMORANDUM

PHPと「セッションID」を利用して同時アクセス人数制限設計を行う

アクセス制限を設けるWEBページを作成する際に、ログイン機能を設けることは一般的ですが、更に同時にアクセスできる人数まで制限したい場合の実装方法をセッションIDを利用した方法でメモ。

同時アクセス人数制限の実装方法

実装したい内容を整理するとログイン処理時に、既にログインしていユーザーの人数をカウントして、上限数を超える場合はアクセスできなくする。といった処理になります。

参考例は、100人を最低1時間の利用で制限。
データベースに「tbl_login 」というテーブルを作成し、そこに「ユーザーネーム(username)」「セッション情報(loginkey)」「セッションの生成時間(logindate)」のカラムを用意しています。

HTML

<form action="login.php" method="post">
<dl>
<dt>ユーザーネーム</dt>
<dd><input type="text" name="username"></dd>
<<dt>パスワード</dt>
<dd><input type="password" name="password"></dd>
</dl>
<ul>
<li><input type="submit" name="submit" value="ログイン"></li>
</ul>
</form>

login.php(PHP)

session_start();

$max = 100;

//1時間よりも前に生成されたセッション情報を削除
$pastdata = date('Y-m-d H:i:s', strtotime('-1 hour'));
$delsql = $db->pdo->prepare('DELETE FROM tbl_login WHERE logindate < :logindate');
$delsql->bindParam(':logindate', $pastdata, PDO::PARAM_STR);
$delsql->execute();

//ログイン処理
if(!empty($_POST['submit'])){
	
	foreach($_POST as $key => $value){
		$dt[$key] = $value;
	}
	
	//入力エラー処理省略

	if(empty($err_msg['error'])){	

		//パスワード照合処理省略
		if($set_password != $dt['password']){

			$err_msg['error']['login'] = error01;

		}else{

			//ログインしている人数をカウント
			$count_list_sql = $db->pdo->query('SELECT * FROM tbl_login);
			$count = $count_list_sql->rowCount();

			if($count <= $max){
				session_regenerate_id(true);
				$user_key = session_id();
				$login_date = date('Y-m-d H:i:s');
			
				//cookieに保存
				setcookie('user_key', $user_key, time()+60*60*24*7);
			
				//セッション情報をデータベースに保存
				$addsql = $db->pdo->prepare('INSERT INTO tbl_login(username, loginkey, logindate) VALUES(:username, :loginkey, :logindate)');
				$addsql->bindParam(':username', $dt['username'], PDO::PARAM_STR);
				$addsql->bindParam(':loginkey', $user_key, PDO::PARAM_STR);
				$addsql->bindParam(':logindate', $login_date, PDO::PARAM_STR);
				$addsql->execute();
			
				$dt = array();
				header("location: ○○○○"); //ログイン完了ページに遷移
				exit;
			}	
		}
	}
}

まずは、ログイン処理時に保存しているセッション情報から対象外となるもの(今回は時間制限で1時間以上経過したもの)を削除し、そこから最大件数に満たない場合はセッション情報を追加するようにしています。

入力処理やパスワードの認証処理(暗号化処理を含む)、データベースへの接続に関する記載は、今回は省略しています。

logincheck.php(PHP)

session_start();
$value = $_COOKIE['user_key'];

//ログインチェック
$check_login_sql = $db->pdo->prepare('SELECT id FROM tbl_login WHERE loginkey = :loginkey');
$check_login_sql->bindParam(':loginkey', $value, PDO::PARAM_STR);
$check_login_sql->execute();
$check_login_count = $check_login_sql->rowCount();

if(!isset($value) or $check_login_count < 1){
	header("location: ○○○○"); //ログインページに遷移
	exit();
}else{
	//セッション情報(時間)を更新
	$login_date = date('Y-m-d H:i:s');
	$updatesql = $db->pdo->prepare('UPDATE tbl_login SET logindate= :logindate WHERE loginkey = :loginkey');
	$updatesql->bindParam(':logindate', $login_date, PDO::PARAM_STR);
	$updatesql->bindParam(':loginkey', $value, PDO::PARAM_STR);
	$updatesql->execute();
}

次に、ページを遷移する度にログインチェックを行うと同時にセッション情報の更新を行います。
これを怠ると時間制限により、他の方がログイン処理を行った際に自動的にログアウトされています。

logout.php(PHP)

session_start();
$value = $_COOKIE['user_key'];

//セッション情報を削除
$delsql = $db->pdo->prepare('DELETE FROM tbl_login WHERE loginkey = :loginkey');
$delsql->bindParam(':loginkey', $value , PDO::PARAM_STR)
$delsql->execute();

//クッキーの削除
setcookie('user_key', '', time()-60);

header("location: ○○○○"); //ログインページに遷移
exit();

最後にログアウト処理の記載です。
そのままにしておいても時間制限でセッション情報は削除されてしまいますが、不正アクセスや個人情報の流出から自身を守るといった安全面や、他の方の利用を制限している可能性があることを考えると自発的に削除できる機能は必要不可欠となります。

RANKING

人気記事

同一カテゴリーの記事