PHPでDigest(ダイジェスト)認証

2007.03.30 Author: えす

PHPでBasic認証を行うことができますが
PHP 5.1.0 以降であれば、PHPでDigest認証を行うことができます。

ソースはこんな感じです。

<?php

define(USER_ID, "admin");
define(PASSWD, "pass");

$realm = 'shain';


if (empty($_SERVER['PHP_AUTH_DIGEST'])) {
    header('HTTP/1.1 401 Unauthorized');
    header('WWW-Authenticate: Digest realm="' . $realm
         . '",qop="auth",nonce="' . uniqid()
         . '",opaque="' . md5($realm) . 'algorithm=MD5"');
    die("ユーザ名とパスワードを入力してください");
}

$data  = array(
        "username" => "",
        "realm"   => "",
        "nonce"   => "",
        "uri"    => "",
        "cnonce"  => "",
        "nc"    => "",
        "response" => "",
        "qop"    => "",
        "opaque"  => ""
        );


$response   = explode(",", str_replace('"', '', $_SERVER['PHP_AUTH_DIGEST']));
$tmp    = null;

foreach ($response as $v) {
  $tmp = explode("=", trim($v));
  
  if (isset($data[$tmp[0]])) {
    $data[$tmp[0]]  = $tmp[1];
    
  // 正しく取得できてない
  } else {
    die("ログインできませんでした。");
  }
}


$hash_1  = md5(sprintf("%s:%s:%s", USER_ID, $realm, PASSWD));
$hash_2  = md5(sprintf("%s:%s", $_SERVER['REQUEST_METHOD'], $data['uri']));
$hash_3  = md5(sprintf("%s:%s:%s:%s:%s:%s", $hash_1, $data['nonce'], $data['nc'], $data['cnonce'], $data['qop'], $hash_2));


if ($data['response'] != $hash_3) {
    die("ログインできませんでした。");
}

echo "ログインしました。";

?>


以下、簡単な説明です。

   $_SERVER['PHP_AUTH_DIGEST']はDigest認証を行った場合、クライアントから送信された「Authorization」の内容が入ります。

   でAuthorizationの内容を、各項目ごとに分割します。

    ちなみに各項目の簡単な説明です。

realm認証名
username入力したユーザ名
uri現ページのURI
nonceサーバ側で生成した乱数
cnonceクライアント側で生成した乱数
qop保護レベル
algorithm暗号方式
ncクライアントからのリクエスト回数(16進数)
responseブラウザ側で生成したハッシュ値

   でハッシュを生成します。

    ハッシュの生成方法は下記の通りです。

1.ユーザ名:realm:パスワード」をmd5でハッシュ値生成
2.「リクエストのメソッド名:URI」をmd5でハッシュ値生成
3.「1のハッシュ:nonce:nc:cnonce:qop:2のハッシュ」をハッシュ値生成

   はブラウザから送られてきた「response」(ブラウザ側で同じ手順で生成したハッシュ値)と比較し、一致すれば通します。

名古屋のWebシステム開発・ネットワーク構築会社 コネクティボへ