pearによるデータベース認証

Basic認証とデータベース認証の最も大きな違いは、セキュリティの高さである。
エックスサーバーの場合、.htpasswdは基本的に外部からアクセスできなくなっているが、 何らかの間違い(例えばディレクトリを間違ってアップロードしてしまった場合)によって外部に漏れる可能性がないとは言えない。 パスワードは暗号化されているものの単なるテキストファイルであり、高度な専門知識を持った人間であれば解読できるかもしれない。 しかしデータベース認証では、ユーザー名とパスワードの両方を知っていないと保存されているデータを見ることができない。 したがってデータベース認証はBasic認証より遥かにセキュリティが高いとされている。

具体的にはどのようにして実装するのか?
「PEAR MDB2」とMySQLを使って説明しているサイトが多いので、そのような環境でおこなうものとする。 実は2~3年前に自分でいろんなコードを書いているのだが、今ではすっかり忘れてしまった。きちんとマニュアルを作成しなかったためだ。 反省して今度はきちんとマニュアルを作っておこう。

XAMPP 1.7.7のpearインストール

まずはpearのインストールをしなければならない。XAMPPは1.7.7でローカルディスクC:の直下に置いてある。 ネットで調べてみると「go-pear.bat」でpearのインストールをするように書いてあるサイトが多いが、 XAMPP 1.7.7には「go-pear.bat」が存在しない。
ここを参考にして「go-pear.phar」を実行してインストールした。

  1. アクセサリーからコマンドプロンプトを起動。
  2. 「cd c:\xampp\php」でディレクトリを変更する。
  3. XAMPPをインストールした状況での「go-pear.phar」は42.5KBで1200行程度のファイルだが、 どうもこのファイルは不完全なもののようでそのためにハマる人が多いらしい。 なので、http://pear.php.net/go-pear.pharからダウンロードしてそれに変更しておく。 このダウンロードしたファイルは、3.9MBで110000行と不完全なファイルの約100倍である。
  4. 「php.exe -d output_buffering=0 PEAR\go-pear.phar」と打ち込んで「go-pear.phar」を実行するとインストールされる。
  5. 「pear install MDB2#mysql」でMySQLのドライバーのインストールを試みる。しかし簡単にはインストールできない。
    この時おそらく「pear channel-update pear.php.net」を実行するように警告が出るので、その通りに実行する。 また、「ERROR: failed to mkdir C:\php\pear\tests\MDB2_Driver_mysql\tests」というエラーメッセージが出る。 「pear config-show」によって確認すると、ディレクトリが「C:\php\pear」というのがいくつかあるのでそれを以下のようにして変更する。
    pear config-set doc_dir C:\xampp\php\pear\docs
    pear config-set cfg_dir C:\xampp\php\pear\cfg
    pear config-set data_dir C:\xampp\php\pear\data
    pear config-set cache_dir C:\xampp\php\pear\cache
    pear config-set download_dir C:\xampp\php\pear\download
    pear config-set temp_dir C:\xampp\php\pear\temp
    pear config-set test_dir C:\xampp\php\pear\tests
    pear config-set www_dir C:\xampp\php\pear\www
    
    しかし変更しようとすると、「PEAR_Config::writeConfigFile fopen('C:\Windows\pear.ini','w') failed (fopen(C:\Windows\pear.ini): failed to open stream: Permission denied)」というエラーが出るので、 管理者権限でコマンドプロンプトを起動して上のディレクトリ変更をおこなう。 (参考サイト
  6. XAMPPのコントロールパネルからMySQLを起動してログインし、適当なデータベースとテーブルを作成する。
  7. 以下のコードを作成してデータベースに接続する。
    <?php
    	$add_path = $_SERVER["DOCUMENT_ROOT"] . "/PEAR";
    	ini_set( "include_path", $add_path . PATH_SEPARATOR . ini_get( "include_path" ) ); 
    	require_once 'MDB2.php'; 
    	$dsn = 'mysql://ユーザー名:パスワード@サーバー名/データベース名'; 
    	$mdb2 =& MDB2::factory($dsn); 
    	$mdb2->setFetchMode(MDB2_FETCHMODE_ASSOC); 
    	$all = $mdb2->queryAll('SELECT * FROM テーブル名'); 
    	print_r($all); 
    ?>
    
    しかし実際に接続してみると、 「Deprecated: Assigning the return value of new by reference is deprecated in ・・・」というエラーメッセージが数多く表示される。
    php.iniの510行目あたりの「error_reporting = E_ALL | E_STRICT」を 「error_reporting = E_ALL & ~E_NOTICE & ~E_DEPRECATED」に変更するとエラーが出なくなる。
  8. 単純なデータベース接続だとこれでOKだが、目的はデータベース認証なのでさらに「Auth.php」を利用する。
    <?php
    function loginFunction($username, $status){
    	if ($status == AUTH_WRONG_LOGIN){
    		print("ユーザー名又はパスワードが間違っています
    "); } print('<form method="post" action='.$_SERVER['PHP_SELF'].'>'); print('<table><tr><td>ユーザー名</td><td><input type="text" name="username"></td></tr>'); print('<tr><td>パスワード</td><td><input type="password" name="password"></td></tr>'); print('<tr><td colspan="2"><input type="submit"></td></tr>'); print("</table></form>'); } //------------------------------------------------------------------------------------------------ $add_path = $_SERVER["DOCUMENT_ROOT"] . "/PEAR"; ini_set( "include_path", $add_path . PATH_SEPARATOR . ini_get( "include_path" ) ); require_once "Auth/Auth.php"; require_once 'MDB2.php'; $dsn = 'mysql://ユーザー名:パスワード@サーバー名/データベース名'; $db = MDB2::connect($dsn); if (PEAR::isError($db)) { die($db->getMessage()); } $params = array( "dsn" => $db, "table" => "テーブル名", "usernamecol" => "username", "passwordcol" => "password", "db_fields" => "*" ); $authobj = new Auth("MDB2", $params, "loginFunction"); $authobj->start(); if ($authobj->getAuth()){ $name = $authobj->getUsername(); print("こんにちは<br>"); print("名前 : ".$name); require_once('hello.php'); } ?>
    以前に作ったスクリプトと異なっている点は、$name = $authobj->getUsername()と認証後のrequire_once('hello.php')。
    $name = $authobj->getUsername()によってユーザー名を取得する。 以前は$name = $authobj->getAuthData("username")によってユーザー名を取得していたが、 今の環境ではこのスクリプトでは取得できなくなった。理由は不明である。
    認証後のrequire_once('hello.php')は、上級者には当たり前かもしれないが私は初めて見てちょっと感心した。
    ちょっと注意すべきことは、パスワードはデフォルトではハッシュ値になるということ。 例えば、パスワードが「fujisan」であれば、そのハッシュ値は「1a7e4c794b2799a1beca143c3cd7041d」なので、 この値を認証データベースのパスワードに設定する必要がある。 パスワードからハッシュ値が一意に決まるのであれば、ハッシュ値を解析してパスワードを取得するのもできるような気がするのだが、 果たしてどうなんだろう?

XAMPP 1.8.2に変更

XAMPP 1.7.7でphpMyAdminからMySQLにログインできなくなった。ネットで調べてみると、XAMPP 1.7.7でよく見られる現象らしい。 それならばと、XAMPP 1.8.2に変更することにした。
XAMPP 1.8.2の方が、コントロールパネルもいろいろと操作しやすい。しかし、MySQLの文字化けが出現。2年前の悪夢がよみがえった。
いつもお世話になっているTATSUO IKURAさんのページを見ながら設定を試みたのだが、どうもうまくいかない。 最終的には、 このページを参考して設定したらうまくいった。
ポイントは、my.iniの「character-set-server=utf8」。 TATSUO IKURAさんのページでは「default-character-set = utf8」になっているが、そのようにするとMySQLが起動できない。
どうせいつかまたハマりそうなので記録しておく。

  1. XAMPP 1.8.2をインストールする。
    通常C:の直下にxamppフォルダが作成される。
  2. c:\xampp\phpにあるphp.iniを 参考サイトを参考にして以下のように設定をおこなう。
    エラー表示変更
    error_reporting = E_ALL & ~E_NOTICE & ~E_DEPRECATED
    日本語表示
    default_charset = "UTF-8"
    地域時間変更
    date.timezone = Asia/Tokyo
    日本語表示    
    [mbstring]
    mbstring.internal_encoding = UTF-8
    mbstring.http_input = auto
    mbstring.http_output = pass
    mbstring.encoding_translation = Off
    [XDebug]
    zend_extension = "C:\xampp\php\ext\php_xdebug.dll"
    xdebug.remote_enable = 1
    xdebug.remote_handler = "dbgp"
    xdebug.remote_host = "localhost"
    xdebug.remote_port = 9000
    
  3. c:\xampp\mysql\binにあるmy.iniを以下のように変更する。
    [mysqld]
    log_error="mysql_error.log"
    
    character-set-server=utf8
    skip-character-set-client-handshake
    ...
    [mysqldump]
    quick
    max_allowed_packet = 16M
    default-character-set=utf8
    
    [mysql]
    no-auto-rehash
    # Remove the next comment character if you are not familiar with SQL
    #safe-updates
    default-character-set=utf8
    
  4. pearのインストール
    XAMPP 1.8.2には、「go-pear.bat」も「go-pear.phar」も存在しない。 XAMPPをアンインストールすれば当然pearもアンインストールされると思うが、どうもほとんどのモジュールはインストールされているようなのだ。
    ただし、MySQLのドライバーだけはインストールされていないので、「pear install MDB2#mysql」とすれば、mdb2を使ったデータベース認証が可能である。
    「No release available for package "pear.php.net/MDB2" install failed」というエラーメッセージが出てインストールできない場合は、 「pear clear-cache」を実行するとインストールできるかもしれない。