Perl/CGI研究室 'PERL-LABO'

Perl/CGI研究室 'PERL-LABO' TOPへ
戻る(History.Back)

.htaccessでパスワードをかける

研究内容

.htaccess と .htpasswd というファイルを使うと、 ディレクトリにパスワード認証をかけることができます。 .htaccess と .htpasswd を生成するCGIプログラムを作成しましょう。

詳細

パスワードをかけたいとき

インターネットというものは基本的に「誰でも自由に見てもいいよ」というものですよね。 ウェブに公開されているものを見るのは、自由です。 逆に言うと、ウェブに公開したら誰に見られても文句は一切いえません。 でも、自分だけとか、友達だけ見えるようにしたいものも時にはあります。 そんなとき、ウェブを閲覧するのにユーザー名とパスワードが必要にする簡単な仕組みがあるんです。 .htaccess と .htpasswd です。

パスワードをかけるときの .htaccess の内容

.htaccess というのはファイル名なんですが、いろんなことに使用できるファイルです。 ファイルの中に決まりに従っていろいろ書いておくと、 今回研究するパスワードの設定とか、その他いろいろ設定ができます。 詳細はまた今度にして、パスワード関連の部分だけ考えましょう。 次のように書きます。

AuthUserFile /〜/.htpasswd
AuthGroupFile /dev/null  
AuthName "パスワードが必要です。"
AuthType Basic  
require valid-user  

AuthUserFile は、この .htaccess が置かれたディレクトリ以下のページに アクセスする許可を与えるユーザー名とパスワードが書かれた .htpasswd というファイルの 場所をフルパスで書きます。 AuthGroupFile は、アクセスを許可するグループの情報が書かれたファイルの場所を 指定するのですが、これはここでは /dev/null としておけばいいようです。 AuthName は、パスワード入力画面に表示されるメッセージ。 AuthType は認証方法で、Basic とするといわゆるベーシック認証となります。 require の valid-user は AuthUserFile で許可されたユーザーだけアクセスを許すという意味ですね。

.htpasswd の内容

.htaccess の内容はそんなに難しくありませんでした。 .htpasswd の方はというと、次のようになります。

username:AjoiejgfNXs2HAS

username のところにユーザー名を書きます。 : の右側は、「暗号化したパスワード」です。 パスワードそのものではありません。 パスワードそのものをこのファイルに書いてしまうと、 このファイルを見ればパスワードが分かってしまいますよね? なので、パスワードを暗号化して元のパスワードが分からないようにしてから、 このファイルに書いておくんです。

この2つのファイルを用意すれば、ディレクトリにパスワードをかけることができます。 さて問題は、「暗号化したパスワード」をどうやって作るのか?ということです。

「暗号化したパスワード」の作り方

これ、Perlだと例によってかーんたんにできてしまいます。次のようにします。

暗号化したパスワード = crypt(元のパスワード, 暗号化の仕方を表す2文字の文字列)

簡単ですねぇ。さすがPerl!です。 でも暗号化の仕方を表す2文字の文字列っていうのが意味不明ですが、これはなんでもいいみたいです。 (ただし使えるのは、英数字 . / のみだそうです。)

.htaccess と .htpasswd を生成するCGIプログラム

これらのファイルを作成するCGIプログラムを作成しましょう。 パスワードをかけたいディレクトリにCGIプログラムを置いて、 CGIプログラムを実行して、ユーザー名とパスワードを入力すると、 以降、そのディレクトリ以下のウェブページにアクセスするには そのユーザー名とパスワードが必要になるっていう感じです。 .htaccess と .htpasswd を自分で作るより簡単です。 .htpasswd の場所をフルパスで書かないといけなかったり、 Windowsだとこのファイル名のファイルは作成できないので、 別のファイル名で作ってアップロードしてからファイル名を変えたり。 面倒ですよね。それにCGIプログラムの勉強になりますから (^^

作成したCGIプログラム

makehtpasswd.cgi
#!/usr/bin/perl

use CGI::Carp qw(fatalsToBrowser);

use Cwd;

print "Content-type: text/html\n";
print "\n";

%form = getformdata();

$action   = $form{'action'};
$message  = $form{'message'};
$username = $form{'username'};
$password = $form{'password'};

# 
# 状態によって、「入力」「確認」「実行」に分岐します
# 

if ($username eq "" || $password eq "" || $action eq "") {
	input();
}
elsif ($action eq "confirm") {
	confirm();
}
else {
	execution();
}
exit;

# 
# 「入力」
# 
sub input
{
	print << "EOM";
.htaccess と .htpasswd を生成します。<br>
このCGIプログラムが置かれたディレクトリ以下がパスワードで保護されます。<br>
<br>
EOM
	if ($message eq "") {
		print "認証メッセージを入力してください。<br>";
	}
	if ($username eq "") {
		print "ユーザー名を入力してください。<br>";
	}
	if ($password eq "") {
		print "パスワードを入力してください。<br>";
	}
	print << "EOM";
<br>
<form action=makehtpasswd.cgi method=post>
<input type=hidden name=action value=confirm>
<table>
<tr><td>認証メッセージ</td><td><input type=text name=message value="$message"></td></tr>
<tr><td>ユーザー名</td><td><input type=text name=username value="$username"></td></tr>
<tr><td>パスワード</td><td><input type=text name=password value="$password"></td></tr>
<tr><td></td><td><input type=submit value="確認画面へ"></td></tr>
</table>
</form>
EOM
exit;
}

# 
# 「確認」
# 
sub confirm
{
print << "EOM";
[ 確認 ]<br>
<br>
<form action=makehtpasswd.cgi method=post>
<input type=hidden name=action value=exec>
<input type=hidden name=message value="$message">
<input type=hidden name=username value="$username">
<input type=hidden name=password value="$password">
<table>
<tr><td>認証メッセージ</td><td>$message</td></tr>
<tr><td>ユーザー名</td><td>$username</td></tr>
<tr><td>パスワード</td><td>$password</td></tr>
<tr><td></td><td><input type=submit value="実行!"></td></tr>
</table>
</form>
EOM
exit;
}

# 
# 「実行」
# 
sub execution
{
	$dir = Cwd::getcwd();

	if (! open(FILE, "> $dir/.htaccess")) {
		print "ファイルが作れませんでした。 $dir/.htaccess";
		exit;
	}
	print FILE << "EOM";
AuthUserFile $dir/.htpasswd
AuthGroupFile /dev/null  
AuthName "$message"
AuthType Basic  
require valid-user  
EOM
	close(FILE);

	$pswdpswd = crypt($password, "zz");

	if (! open(FILE, "> $dir/.htpasswd")) {
		print "ファイルが作れませんでした。 $dir/.htpasswd";
		exit;
	}
	print FILE << "EOM";
$username:$pswdpswd
EOM
	close(FILE);

	print << "EOM";
成功しました。<br>
以降、このCGIスクリプトを含めて、パスワード認証がかかります。<br>
試しにリロードしてみてください。
EOM
}

# フォームデータを連想配列に格納します
sub getformdata
{
	local $rawdata;
	local %formdata;
	local @inputs;
	local($input, $name, $val);

	if ($ENV{'REQUEST_METHOD'} eq "POST") {
		read(STDIN, $rawdata, $ENV{'CONTENT_LENGTH'});
	}
	elsif ($ENV{'REQUEST_METHOD'} eq "GET") {
		$rawdata = $ENV{'QUERY_STRING'};
	}

	@inputs = split('&', $rawdata);

	foreach $input (@inputs) {
		($name, $val) = split('=', $input);
		$name =~ tr/+/ /;
		$val  =~ tr/+/ /;
		$name =~ s/%([A-Fa-f0-9][A-Fa-f0-9])/pack("C", hex($1))/eg;
		$val  =~ s/%([A-Fa-f0-9][A-Fa-f0-9])/pack("C", hex($1))/eg;
		$formdata{$name} = $val;
	}

	return %formdata;
}

実行結果

…よく考えると、このCGIプログラムを実行するとこのウェブページも見えなくなってしまいます。 ですので、実行しないでください (^^;

詳細

今回のCGIプログラムはとても重要な情報を入力します。 もし、パスワードを間違えて入力してしまうと、 パスワード認証がかかるようになってから、パスワードが分からなくて困ってしまいます。 そこで、確認画面を表示するようにしました。 1つのCGIプログラムで、入力、確認、実行の3役をこなしています。 ポイントは、<input type=hidden action=〜> というやつです。 画面には表示されませんが、「次にすること」を指定しています。 これで、中で分岐することができますね。 また、ユーザー名やパスワードが空欄だった場合はおかしなことになってしまいますので、 そういう場合は実行をせずに入力画面に戻るようになっています。 簡単なCGIプログラムですが、なかなかよく出来ているんじゃないでしょうか。

なお、パスワード認証はウェブブラウザでアクセスするときに発生するものです。 FTPでアクセスするときはこの認証はかからないので、パスワードを間違えて入力しちゃったり、 パスワード認証を無くしたりしたい場合は、FTPでアクセスして .htaccess と .htpasswd を削除しちゃえば大丈夫です。

よかったら試してみてください。 仲間だけに公開するウェブページが作れますよ! 仲間うちの掲示板とかに使うのもいいかも知れませんね。

Perl/CGI研究室 'PERL-LABO' TOPへ
戻る(History.Back)

Copyright (c) 'PERL-LABO' All Rights Reserved.  リンクフリーです。