#012
posted on 2021.01.03 (Sun) 2022.09.16 (Fri)

PHPでベーシック認証。

PHPで、HTTPヘッダーを送信するheader()関数と、Webサーバーのヘッダー情報が取得できるマジック定数の$_SERVER(サーバー変数)を使用したベーシック認証の実装方法のメモ。

※ ベーシック認証の仕組みの詳細は前の記事を参照。

※ ベーシック認証はApacheの拡張機能なので、サーバーがNginxなどの場合は設定を変更しなければ利用できない。

 

IDとパスワードをハッシュ化

phpファイルに記述しておく認証確認用の「ID」と「パスワード」は、簡易なセキュリティーとしてpassword_hash()関数でハッシュ化したハッシュ値を使い、実際のIDとパスワードはどこにも記述しないようにする。

※ このハッシュ値とpassword_verify()関数を使って認証する。

 

password_hash()関数で作られたハッシュ値には、アルゴリズム、コスト、ソルトの情報が含まれているので、ハッシュ値だけあれば認証できる。

<?php
$str = 'ハッシュ化したい文字列';
echo password_hash($str, PASSWORD_DEFAULT);
?>

password_hash(‘ハッシュ化したい文字列’, ‘ハッシュ化に使うアルゴリズム’) : 指定した文字列を指定したハッシュ化アルゴリズムでハッシュ値に変換する。「PASSWORD_DEFAULT」を指定するとPHPのバージョンにより最も強力とされるアルゴリズムが使われる(PHP 5.5.0の時点ではbcrypt)。

 

 

ベーシック認証の実装

挙動の流れ

  1. header()関数で、クライアントにベーシック認証を要求するHTTPのレスポンスを返す。
  2. クライアントから再度送られたHTTPリクエストヘッダーに含まれる認証情報を$_SERVER(サーバー変数)で取得。
  3. 入力されたIDとパスワードをpassword_verify()関数で照合してif文で分岐。
  4. 認証情報が正しければそのまま通常のページを出力、間違っていればアラートを表示してページの出力を停止。
<?php
// 事前にハッシュ化したIDとパスワードを保持。
$hashedId = '$2y$10$j4Tf7VzCfaUj9noQaEyK2.3uPE72V8mNvRx77vy/F1YAOAwbEtW6q';// 「id」のハッシュ値
$hashedPass = '$2y$10$KKyNuNgtmvBnd70jS5CeS.nnGeHZmeMJpYjsJxYNMR.lAb3XQ9STi';// 「pass」のハッシュ値

// 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を返す。true以外の場合はfalseを返す。

$_SERVER : サーバー変数が連想配列で格納されている。

$_SERVER[‘PHP_AUTH_USER’] : HTTP認証で入力されたユーザー名を返す。

$_SERVER[‘PHP_AUTH_PW’] : HTTP認証で入力されたパスワードを返す。

die(‘文字列’) : 文字列が指定されていれば出力してスクリプトの終了、文字列が無ければそのままスクリプトの終了。

password_verify(‘認証したい文字列’, ‘password_hash()で作ったハッシュ値’) : 指定した文字列が指定したハッシュ値とマッチする場合にtrueを返す。

 

 

この記事のURL

https://memo.ag2works.tokyo/post-497/

Copyコピー
この記事のタイトル

PHPでベーシック認証。 | memo メモ [AG2WORKS]

Copyコピー
この記事のリンクタグ

<a href="https://memo.ag2works.tokyo/post-497/" target="_blank" rel="noopener">PHPでベーシック認証。 | memo メモ [AG2WORKS]</a>

Copyコピー
※ フィールドをクリックでコピーするテキストの編集ができます。

この記事へのコメント

コメントの書き込みはまだありません。

  • コメント内のタグはエスケープ処理され、文字列として出力されます。
  • セキュリティーのため、投稿者のIPアドレスは取得されます。
  • 管理者が内容を不適切と判断したコメントは削除されます。
  • このフォームにはスパム対策として、Googleの提供するreCAPTCHAシステムが導入されています。
    (Google Privacy Policy and Terms of Service.)