jiichan.com

PROGRAMMING

ログイン画面の作成

サイト作りでは、特定のメンバーだけにオープンしたいページもあります。 その場合、ユーザーの認証が必要となりますが、認証方法について考えます。
まずよく使われている、 「Basic認証(基本認証)」と「フォーム認証」を作ってみます。

Basic認証(基本認証)

Basic認証の場合はページを開く際、ユーザー認証に認証ダイアログを使う。
Basic認証では.htaccessファイルを作り、

1. AuthType:認証方法(この場合はBasic) 2. AuthName:認証領域名(表示されるメッセージ) 3. AuthUserFile:ユーザ名・パスワード格納ファイルの場所 4. require valid-user(認証された場合はアクセスを許可するという意味)
を記述することになりますが、 今回は.htaccessファイルを作らずPHPのheader関数で対応しました。


<?php
header("charset=UTF-8");	// 出力文字コード 

if(!isset($_SERVER['PHP_AUTH_USER'])){
	// 認証ダイアログの表示
	header('WWW-Authenticate: Basic realm="Administrator Page"');
	header("HTTP/1.0 401 Unauthorized");
	// ダイアログでキャンセルボタンがクリックされた場合
	die("このページはログインが必要です");
}else{
	//ダイアログでOKがクリックされた場合はユーザー名とパスワードを確認し
	if ($_SERVER['PHP_AUTH_USER'] == "user" and $_SERVER['PHP_AUTH_PW'] == "pass"){
		// 下部のhtmlを表示
	}else{
		// ユーザー名・パスワードが不一致の場合は認証ダイアログを表示
		header('WWW-Authenticate: Basic realm="Administrator Page"');
		header('HTTP/1.0 401 Unauthorized');
	}
}
?>
<!DOCTYPE html>
<html lang="ja">
	<head>
		<meta charset="UTF-8">
		<title>ログイン画面の作成(Basic認証):sample</title>
	</head>
	<body>
		<p>おめでとうございます。ログインされました。</p>
	</body>
</html>

上のコードでは、ユーザー名やパスワードを直接コード上に書いていますが、 セキュリティ上まずいので通常は公開フォルダの外に置いておきます。

Basic認証サンプル

※ Basic認証は、一度認証に通ればブラウザを終了するまで何度でも再認証なしでアクセスでき、 途中で他のサイトに移動して戻ってきても認証が不要となります。
また「ログアウト機能が無い」など、 フォーム認証にくらべてやや問題点もあるようです。

そこで、フォーム認証

HTMLのフォームを利用してユーザーやパスワードの認証を行います。
ログイン状態の保持・確認には方法がいくらかありますが、セッションを使う方法が一般的だと思いますので、 セッションを使ってみます。

セッションでは
・ リクエストをしてきたユーザー(PC)を識別するために→セッションID ・ ログイン状態や購入商品などユーザー(PC)の情報を保持のために→セッション変数 を使います。

セッションのおもなポイントは 1. session_start()はHTMLタグよりも前に記述する 2. セッションの有効期限が認証の有効期限となる 3. デフォルトの設定では,Webブラウザを閉じるまで同じセッションが有効 4. セッションに有効期限を設定するのはsession_set_cookie_params()関数 秒数単位で指定するので,1時間有効にするなら60×60(=3600)秒間となる この関数はsession_start()よりも前に実行しておかなくてはならない 5. ユーザー名やパスワードはクリアテキストでサーバーに送信されるので、SSLなどの使用を検討したほうがよい です。

ログインするためのページ

ログイン画面はログイン専用のページを作るか、すでにあるページに付加します。
次のコードがログインのサンプルコードでログイン専用のページになっています。


<?php
session_start();

$errorMessage = "";
// ログインのリクエストがあったとき
if(isset($_REQUEST["loginbtn"])){
	$user = $_REQUEST["username"];
	$pass = $_REQUEST["password"];
	// DBなどでユーザー名とパスワードの確認
	if($user == "user" && $pass == "pass"){
		// 認証成功
		session_regenerate_id(true);		// 念のためセッションIDを変更
		$_SESSION["user"] = $user;
		$_SESSION["code"] = "10001";
		header("Location: ./hoge.php");	// 指定のページに移動
		exit();
	}else{
		// 認証失敗
		session_destroy();	// セッションを破棄
		$errorMessage = "ユーザー名、パスワードのいずれかに誤りがあります";
	}
}
?>
<!DOCTYPE html>
<html lang="ja">
<head>
	<meta charset="UTF-8">
	<title>認証サンプル(ログイン画面)</title>
</head>
<body>
<p>ログインサンプル</p>
<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
	<p>ユーザー名<input type="text" name="username"></p>
	<p>パスワード<input type="password" name="password"></p>
	<p><input type="submit" name="loginbtn" value="ログイン"></p>
</form>
<p id="loginerror"><?php echo $errorMessage ?></p>
</body>
</html>

2行目:session_start();
この関数は、セッションが開始されているクライアントからアクセスがあった場合に 新たにセッションを開始しなおすのではなく、サーバ側で保存されているセッション変数が 利用できるように準備してくれます。
3行目:session_regenerate_id(true);
引数(true)を指定しないと、古いセッションファイルを削除しないので、実行ごとにゴミファイルが 増えることになります。
15行目では、認証が通ったので指定のページに移動することになります。

ログイン後に呼ばれるページ

ログインが成功した後には指定のページが呼ばれますが、そのページではログイン時にセットされたセッション変数でログインが許可されたユーザーであることが確認できます。
次が認証通過後のページです。


<?php
// セッションを開始(セッション変数を利用できる)
session_start();

if(!isset($_SESSION["user"])){	// ログインしているか確認
	header("Location: ./login.php");
	exit();
}

echo "おめでとうございます。<br>";
echo $_SESSION["user"]."さん<br>";
echo "ログイン成功です。";
?>
<!DOCTYPE html>
<html lang="ja">
<head>
	<meta charset="UTF-8">
	<title>認証サンプル(認証成功後の画面)</title>
</head>
<body>
	<p><a href="./logout.php">ログアウト</a></p>
</body>
</html>

ログインが許可されたユーザーかを5行目で確認し、直接このページにアクセスされた場合など認証されていない場合は6行目でログインのページに移動します。

最後はログアウト

ログアウト時にはセッションファイルの破棄の前に必ずセッション変数を初期化します。 セッション変数はセッションファイルを破棄しても残るため、この処理が必要です。 また、セキュリティの意味からもクライアント側のクッキーも削除します。


<?php
session_start();
$_SESSION = array();	// セッション変数を初期化

// クッキーを使っている場合はセッションクッキーも削除
if(ini_get("session.use_cookies")){
	$params = session_get_cookie_params();
	setcookie(
		session_name(),       // セッション名
		'',                   // 値を空に
		time() - 42000,       // 有効期限を過去に(結果的に削除)
		$params["path"],      // 情報が保存されている場所のパス
		$params["domain"],    // クッキーのドメイン
		$params["secure"],    // セキュアな接続でのみ送信する
		$params["httponly"]   // HTTP を通してのみアクセス可能
	);
}
session_destroy();	// セッションを破棄
?>
<!DOCTYPE html>
<html lang="ja">
<head>
	<meta charset="UTF-8">
	<title>認証サンプル(ログアウト画面)</title>
</head>
<body>
	<p>ログアウトされました</p>
	<p><a href="./login.php">ログイン画面へ</a></p>
</body>
</html>

認証やページ間のデータ保持にはセッションの利用が欠かせないということがよく分かりました。

フォーム認証サンプル