PHPでベーシック認証。
PHPでHTTPヘッダーを送信するheader()関数と、Webサーバーのヘッダー情報が取得できるマジック定数の$_SERVER(サーバー変数)を使用したベーシック認証の実装のメモ。
ベーシック認証の仕組みの詳細は前の記事を参照。
IDとパスワードをハッシュ化
PHPファイルに記述しておく認証確認用のIDとパスワードは簡易なセキュリティーとしてpassword_hash()関数でハッシュ化し、実際のIDとパスワードはどこにも記述しないようにする。
<?php
$str = 'ハッシュ化したい文字列';
echo password_hash($str, PASSWORD_DEFAULT);
?>
password_hash(‘ハッシュ化したい文字列’, ‘ハッシュ化に使うアルゴリズム’) : 指定した文字列を指定したハッシュ化アルゴリズムでハッシュ値に変換する。「PASSWORD_DEFAULT」を指定するとPHPのバージョンにより最も強力とされるアルゴリズムが使われる(PHP 5.5.0の時点ではbcrypt)。
このハッシュ値とpassword_verify()関数を使って認証する。
password_hash()で作られたハッシュ値には、アルゴリズム、コスト、ソルトの情報が含まれているので、ハッシュ値だけあれば認証できる。
ベーシック認証の実装
挙動の流れ
- header()関数で、クライアントにベーシック認証を要求するHTTPのレスポンスを返す。
- クライアントから再度送られたHTTPリクエストヘッダーに含まれる認証情報を$_SERVER(サーバー変数)で取得。
- 入力されたIDとパスワードをpassword_verify()関数で照合してif文で分岐。
- 認証情報が正しければそのまま通常のページを出力、間違っていればアラートを表示してページの出力を停止。
<?php
// 事前にハッシュ化したIDとパスワードを保持。
// 「id」のハッシュ値
$hashedId = '$2y$10$j4Tf7VzCfaUj9noQaEyK2.3uPE72V8mNvRx77vy/F1YAOAwbEtW6q';
// 「pass」のハッシュ値
$hashedPass = '$2y$10$KKyNuNgtmvBnd70jS5CeS.nnGeHZmeMJpYjsJxYNMR.lAb3XQ9STi';
// HTTPリクエストのAuthorizationヘッダーの有無($_SERVER['PHP_AUTH_USER']の有無)を確認。ユーザーが一度でもIDとパスワードを入力していると変数に格納される。
if(!isset($_SERVER['PHP_AUTH_USER'])){
// Authorizationヘッダーが無い場合の処理。
// header()関数でWWW-Authenticateヘッダーを含めた401のHTTPレスポンスを返して認証情報を要求。
header('Content-type: text/html; charset=utf-8');
header('WWW-Authenticate: Basic realm="Please input ID and PASSWORD."');
header('HTTP/1.1 401 Unauthorized');
// クライアント側の認証要求でユーザーがキャンセルした場合の処理。
// die関数でメッセージを出力してスクリプトの実行を終了させる。
die('<p>このページを閲覧するにはログインが必要です。</p>');
}else{
// Authorizationヘッダーがある場合の処理。
// ユーザーが入力したIDとパスワードを変数へ代入。
$inputId = $_SERVER['PHP_AUTH_USER'];
$inputPass = $_SERVER['PHP_AUTH_PW'];
// 受け取った認証情報と保持しているハッシュ値を照合して正否判定。
if(!(password_verify($inputId, $hashedId)) || !(password_verify($inputPass, $hashedPass))){
// 認証情報が間違っている場合の処理。
// 再認証のために401のHTTPレスポンスを再度返す。
header('Content-type: text/html; charset=utf-8');
header('WWW-Authenticate: Basic realm="Please input ID and PASSWORD."');
header('HTTP/1.1 401 Unauthorized');
// 再認証の要求でユーザーがキャンセルした場合の処理。
die('<p>認証情報が間違っています。</p>');
}else{
// 認証情報が正しい場合の処理。
// 何もせずにベーシック認証以下に続く処理を実行。
}
}
?>
<!DOCTYPE html>
<html lang="ja">
//通常のページの記述。
</html>
header(‘ヘッダー文字列’) : 生のHTTPヘッダーを送信する。
isset(‘変数’) : 指定された変数が宣言されていて、nullではないときにtrueを返す。
$_SERVER : サーバー変数が連想配列で格納されている。
$_SERVER[‘PHP_AUTH_USER’] : HTTP認証で入力されたユーザー名を返す。
$_SERVER[‘PHP_AUTH_PW’] : HTTP認証で入力されたパスワードを返す。
die(‘文字列’) : 文字列が指定されていれば出力してスクリプトの終了、文字列が無ければそのままスクリプトの終了。
password_verify(‘認証したい文字列’, ‘password_hash()で作ったハッシュ値’) : 指定した文字列が指定したハッシュ値とマッチする場合にtrueを返す。