今からスタート! PHP
第8回 ユーザ名とパスワードを入力させる
BASIC認証とは?
あなたは,Webページにアクセスしようとしたとき,図1のような入力画面が表示された経験はないでしょうか。
これは上の入力欄にユーザ名を,下の入力欄にパスワードを入力して「OK」をクリックしたあと,Webページ側がデータと照合して正しいと判断されれば,Webページを閲覧できるというものです。これを実現するしくみをBASIC(ベーシック)認証といいます。BASIC認証の仕様はRFC2617で決められています。
最近はセキュリティの関係で,ログイン時にユーザ名/パスワードを入力するページを用意している例が多くなり,BASIC認証のみでログインするページをあまり見かけなくなりましたが,そのしくみを知っておくと,PHPプログラミングに役立ちます。
HTTPヘッダの設定
どんなことに役立つかというと,それはHTTPヘッダの設定です。HTTPヘッダとは,WebサーバとWebブラウザとの間で交わされる会話の内容で,通信の方法を決めたり,通信後の状態を知るときなどに使われています。
これらは通常,両者の間で自動的に送受信されているため,一般的なWebアクセスを行っているだけでは,ユーザがその存在を知ることはあまりありません。ですが,たまに「404 Not Found」「403 Forbidden」などと表示されるものが,実はHTTPヘッダの一部なのです。
PHPプログラミングを行ううえで知っておきたいのは,とくにWebブラウザに向けて発信するHTTPヘッダの内容です。今回は,そのうちのいくつかを紹介します。
ユーザ名/パスワードは入力されたか
BASIC認証が必要であることを伝える前に,アクセスしてきたユーザはすでにWebブラウザでユーザ名/パスワードの入力を済ませたのかどうかを知っておく必要があります。なぜなら,もしそれらを入力済みであれば,内容が正しいものかを判定する処理に移らなくてはならないからです。
これは$_SERVER[ 'PHP_AUTH_USER' ] という変数が設定されているかどうかで判断します。つまりisset( $_SERVER[ 'PHP_AUTH_USER' ] )です。
BASIC認証をさせる
もしユーザがまだユーザ名/パスワードの入力を済ませていないのであれば,このページはBASIC認証が必要であることをWebブラウザに伝えます。それには,2つのHTTPヘッダを設定します。header()はいずれもHTMLタグより先に記述しておかなくてはなりません。
header( 'WWW-Authenticate: Basic realm="....."' );
header( 'HTTP/1.0 401 Unauthorized' );
このとき,realm="......"の.....部分には,入力欄の上に表示するメッセージを記述します。日本語では文字化けする場合がありますので,メッセージは英文にしておいたほうがよいでしょう。
メッセージを"Members Only"とした場合の,Webブラウザの種類ごとの表示例を図2から図4に示します。同じメッセージを発信するにしても,このようにWebブラウザの種類によって表示される内容が異なることを知っておいてください。
ユーザ名/パスワードを照合する
アクセスしたユーザがユーザ名/パスワードの入力を済ませていたら,それを照合する処理を行います。登録済みのデータをファイルやデータベースから読み込み,入力されたものと等しいかを判断すればよいので,一般的なプログラミングで可能です。
ユーザが入力したユーザ名/パスワードは,それぞれ以下の変数に保存されています。これらの変数の内容(特にパスワード)は,テスト用でない限り画面に表示すべきではないのは,いうまでもないことでしょう。
ユーザ名 : $_SERVER[ 'PHP_AUTH_USER' ]
パスワード : $_SERVER[ 'PHP_AUTH_PW' ] // 画面に表示すべきでない
会員用のページに移動する
照合の結果,正規のユーザであると判断したあと,会員用のページに移動するという処理はよく行われます。自動的にページを移動することをリダイレクトといいます。このときは,以下のようにしてヘッダを設定します。こうすると,Webブラウザが指定されたURLに再度アクセスしなおします。その結果,WebブラウザのURL入力欄が書き換えられます。
header( 'Location: 移動先のURL' );
プログラミング例
最後に,これらの処理を行うソースコードの例をリスト1に示します。これはユーザ名/パスワードにそれぞれusername/passwordと入力されたら,同階層のmembers.phpに移動するという処理を行うものです。<html>...</html>の部分は,入力画面でキャンセルがクリックされたときに表示される内容(図5)が記述されています。
もし入力された内容が間違っていたら,「403 Forbidden」を送信し,アクセスが許されないことをWebブラウザに知らせます。このときIE7では図6のように表示されます。FirefoxやOperaでは,画面に何も表示されません。
リスト1 BASIC認証のための処理を行う例
<?php
// BASIC認証が行われたかどうか
if ( !isset( $_SERVER[ 'PHP_AUTH_USER' ] ) ) {
// BASIC認証が必要(realm="..."は入力欄の上に表示させるメッセージ)
header( 'WWW-Authenticate: Basic realm="Members Only"' );
// ステータスコード(Webサーバのアクセス状況をWebブラウザに伝える)
header( 'HTTP/1.0 401 Unauthorized' );
// ここに exit; を記述して,これ以降の処理をしないこともある
} else {
// 入力されたユーザ名とパスワードが正しいかを判断する
// ここでは文字列を直接比較しているが,実際にはデータベース
// など多くのデータを保存できるしくみを用いることが多い
if ( $_SERVER[ 'PHP_AUTH_USER' ] == 'username' &&
$_SERVER[ 'PHP_AUTH_PW' ] == 'password' ) {
// メンバー用のページにリダイレクト
header( 'Location: members.php' );
} else {
// アクセスが許されないことをWebブラウザに知らせる
header( 'HTTP/1.0 403 Forbidden' );
// 以降の処理を行わない(画面を表示しない)
exit;
}
}
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>PHPによるBASIC認証</title>
</head>
<body>
<h3>PHPによるBASIC認証</h3>
<p style="font-weight : bold; color : red;">ユーザ名とパスワードを正しく入力してください</p>
</body>
</html>
パスワードは保存時に暗号化
パスワードがどのように保存されているかは,セキュリティを守る上で重要です。
もしパスワードを入力されたそのままの状態で保存してしまっていると,データにアクセスする権限がある人がそれを盗み見て,あたかも正規に登録したユーザであるかのようにアクセスしてしまうというリスクがあります。
そのため,少なくともパスワードは保存する時点で暗号化し,仮に盗み見られても容易には内容を認識できないようにしておくべきでしょう。


