ホームページを作る上で、特定の人にだけ見せたいページが出てくるでしょう。そのようなページでよく、アカウントとパスワードを入れさせるページを見たことがあると思います。これを「Basic認証」と呼びます。ブラウザーによって認証画面が異なります。
Internet Explorer 7 の場合

Firefox 3.0 の場合

Opera 9.5 の場合

実際に、お使いのブラウザーではどのような画面がでるかを、こちらでお試しください。
このBasic認証は、「.htaccess
」と「.htpasswd
」いうファイルに記述すれば実現することができます。特に指定がなければ「.htaccess
」をおいたディレクトリ配下のすべてのコンテンツに対して制限がかかります。
記述例
AuthUserFile /home/futomi/.htpasswd
AuthGroupFile /dev/null
AuthName "Secret Area"
AuthType Basic
require valid-user
<Files ~ "^.(htpasswd|htaccess)$">
deny from all
</Files>
太字の行について説明します。この部分を環境に合わせて書き換えなければいけません。その他の行については、そのまま書き加えてください。
AuthUserFile
パスワードファイルの指定です。ここでの指定は、サーバのルートディレクトリからのフルパスで記述しなければいけません。
AuthName
Basic 認証をかける領域名の指定です。上の図の例では、「Secret Area」の部分です。"(ダブルクォーテーション)」で囲まれた部分は、自由に書き換えてください。ただし、「"(ダブルクォーテーション)」は入れないでください。
Files
これは、なくても問題ありません。ただし、「.htaccess
」や「.htpasswd
」はやはり見せたくありません。そのために、この記述を加えることをお勧めします。
記述例
taro:FeNpx1.147CVA
hanako:X6ntcZ021IxMw
.htpasswd
に記載される情報は、アカウント名とパスワードです。アカウント名とパスワードは「:(コロン)」で区切られます。複数のアカウントを指定する場合には、改行をして次の行に記述します。パスワードについては、暗号化された状態で保存される必要があります。暗号化は、何かしらツールが必要なのですが、ここでは、パスワードを入れたら、暗号化された文字列を出力するCGI作ってみましょう。
パスワードの暗号化は、UNIXのパスワードの暗号化と同じです。この手の内容のホームページでしばしば、"Base64で暗号化" と書いてあるページを見かけたことがありますが、これは間違いです。
ちなみに Base64 は暗号化ではなく符号化です。ブラウザーからサーバへリクエストをする際には、アカウント、パスワードともに、Base64 で符号化されて送信されます。これは HTTP/1.1 で規定されています。
Base64 で符号化された文字は、簡単に元に戻せます。つまり、Base64とは元に戻せるように考案された符号化方式です。しかし、UNIXのパスワードの暗号化は元に戻すために考案されたものではありません。つまり、暗号化された文字列が発見されたとしても、すぐにはパスワードを解析することができないのです。しかし不可能ではありません。したがって、それを防ぐためにも、「.htpasswd
」ファイルは、見ることができないようにする必要性があります。
さて、話は元に戻って、Perlでパスワードを暗号化するにはどうしたらいいのでしょう。実は非常に簡単なスクリプトを組むだけで実現できます。
Perlのcrypt
関数を使って暗号化します。crypt
関数の使い方は、以下のとおりです。
crypt(PLAINTEXT, SALT)
PLAINTEXT
の部分は、暗号化したい文字列です。SALT
の部分は、大文字・小文字アルファベットと 0 ~ 9 の数字、そして、「.
(ドット)」「/
(スラッシュ)」のいずれか2文字です。SALT
は、暗号化する際のキーとなるもので、PLAINTEXT
が文字列でも、SALT
を変えることによって暗号化文字列が異なってきます。つまり同じ PLAINTEXT
に対して、4096通りの暗号化パスワードが生成しうるわけです。
SALT
は、固定で決めてしまってもいいのですが、できる限り複雑にするために、生成するたびにランダムな文字列を指定するのが良いでしょう。いろいろな方法があるかと思いますが、ここでは、rand
関数を使ってランダムな2文字を抽出します。
#!/usr/bin/perl
use strict;
use CGI;
my $q = new CGI;
my $pass = $q->param('pass');
my $encpass = &encrypt_passwd($pass);
print "Content-type: text/plain\n\n";
print ${encpass};
exit;
sub encrypt_passwd {
my($pass)=@_;
my @salt_set = ('a'..'z','A'..'Z','0'..'9','.','/');
srand;
my $idx1 = int(rand(63));
my $idx2 = int(rand(63));
my $salt = $salt_set[$idx1] . $salt_set[$idx2];
return crypt($pass, $salt);
}