Perlのおべんきょう

このページは僕がPerlについて試行錯誤がんばる感じのところです。
参考になるものが生まれれば幸いです。


ログイン画面を作ろう
DB接続を利用して、よくあるログイン画面を作ってみます。
*DBはMySQLを使用します。
DBへの接続に関しては前回のDBに接続を参考にしてください。

プログラムの構想としてはこんな感じで作ってみようと思います。
構想
logoin.cgi ─(入力データ)→ login.cgi ─┬─(成功)─→ 成功ページへ
                        │
                        └─(失敗)─→ 失敗メッセージを表示

以降、GETやらPOSTというデータ送信方法の呼称が出てきますので灰色の部分がその説明です。
*GETはデータをURLの後ろにくっつけて送信します。(例:http://〜.com/login.cgi?name=a-bs&pass=test)
*これはログイン画面などパスワードなどの個人情報を扱う場合とても危険です。(URLでばれる上に、上記のアドレスを打ち込めば認証画面なしでページに移動するからです。)
*そこで考えられたのがPOST方式でこれはURLにくっつけて送信はせず、送る側でデータを"POSTで〜のデータを送りますよ"といったような記述をします。
*ですので、ログイン画面ではPOST方式でデータのやり取りを行います。
*ここまで書くとGETのメリットがないように思えますが、メリットのあるいい例としてはGoogleなどの検索サイトがあります。
*GoogleなどはGETを使用しているので検索後のURLはこうなります。(http://www.google.co.jp/search?hl=ja&rlz=1C1CHMG_enJP291&q=a-bs+appli&btnG=検索&lr=)
*この場合、他人に上記の検索結果ページを教えたい場合、上のURLをコピーして教えてあげるだけで済むようになります。

ユーザが最初に接続した場合はログイン画面のみが表示されます。
こんなの↓
ユーザ名
パスワード

この画面から、ログインボタンを押した場合、login.cgiからはHTMLのformタグを使い、POSTで再び自分(login.cgi)にデータを飛ばします。
formタグから送信されるデータは ユーザ名(name) パスワード(pass) のほかに、送信ボタンが押されて呼び出されたのかどうかを判別するために、hidden属性でtypeを送ることにします。
んで、ユーザ名とパスワードが正しい場合は成功画面へ。(別に作ります)
間違っている場合は、赤文字で注意分を付け足した上記のログイン画面に戻るようにします。
こんなの↓
ユーザ名
パスワード
* ユーザ名かパスワードが間違ってます

では、上記の構想で作ってみます。
ちなみにDBのテーブルには以下のデータを登録しておきました。
LOGINテーブル
ACCOUNTPASSWORD
a-bspassword
testtest
上記のどちらかのIDとパスワードで接続できることとします。

ではようやくperlの作成に入ります。
実行ファイルはlogin.cgiと名付けました。
ファイル名login.cgi
属性755
* login.cgi
#!/usr/bin/perl -w

$success = "http://abebas.sub.jp/perl/login/success.txt";

# エラーをブラウザに表示
use CGI::Carp qw(fatalsToBrowser);
# DBIモジュール
use DBI;

# データの取得
if ($ENV{'REQUEST_METHOD'} eq "POST") {
	# POSTの場合
	read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
} else {
	# GETの場合
	$buffer = $ENV{'QUERY_STRING'};
}

# 受信したデータを分割
@pairs = split(/&/, $buffer);

# さらに各データに分割
foreach $pair (@pairs) {
	($name, $value) = split(/=/, $pair);
	# ハッシュ変数に格納
	$key{$name} = $value;
}

# ログインボタンが押されてきた場合は&loginへ
if($key{'type'} eq 'send'){
	&login;
} else {
	&html;
}


# sub login

sub login{
	# ユーザ名とパスワード
	$user = 'ユーザ名';
	$pass = 'パスワード';

	# DBへ接続
	$db = DBI->connect('DBI:mysql:DB名:サーバ名', $user, $pass);

	# 命令
	$sth = $db->prepare( "select * from LOGIN" );

	# 実行
	$sth->execute;

	while( @rows = $sth->fetchrow_array ){
		$login_id = $rows[0];
		$login_pw = $rows[1];

		# 認証
		if($key{'name'} eq $login_id && $key{'pass'} eq $login_pw){
			# 認証に成功した場合、下記のURLへ飛ばす
			print "Location: $success\n\n";
		}
	}
	&html('* ユーザ名かパスワードが間違ってます');

	# 切断
	$db->disconnect;
}


# sub html

sub html{
	# 引数受取
	@msg = @_;

	# 出力
	print "Content-type: text/html\n\n";
	print "<html>";
	print "<head>";
	print "<title>ログイン画面</title>";
	print "</head>";
	print "<body>";
	print "<form action=login.cgi method=POST>";
	print "<input type=hidden name=type value=send>";
	print "<table border=1 bordercolor=orange width=350>";
	print "<tr><td><center>";
	print "<table width=340>";
	print "<tr><td>ユーザ名 </td><td><input type=text size=20 name=name></td></tr>";
	print "<tr><td>パスワード </td><td><input type=password size=20 name=pass></td></tr>";
	print "<tr><td> </td><td><input type=reset value=取り消し><input type=submit value=ログイン></td></tr>";
	foreach $str (@msg){
		print "<tr><td colspan=2><font color=red><b>$str</b></font></td></tr>";
	}
	print "</table>";
	print "</table>";
	print "</body>";
	print "</html>";
}

exit;

完成したのがこちら(直リン)です。
↓がインラインフレームによる完成図です。

ユーザ名 a-bs パスワード password または
ユーザ名 test パスワード test でログインできます。

ソースの補足
$ENV{'REQUEST_METHOD'}
→ POSTとGETのどちらで送信されたかを受け取ります(POSTならPOST)。

# POSTの場合
read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
# GETの場合
$buffer = $ENV{'QUERY_STRING'};
→ それぞれ$bufferという変数に値を入れています。
  それぞれの値は type=send&name=user&pass=pwd のような形で送信されます。

@pairs = split(/&/, $buffer); → ここで、$bufferの値はそれぞれ配列@pairsの中に & ごとに切り離されて格納されます。   例として上の値は、@pairs = { 'type=send', 'name=user' , 'pass=pwd'}; のように格納されています。
foreach $pair (@pairs) { ($name, $value) = split(/=/, $pair); # ハッシュ変数に格納 $key{$name} = $value; } → さらにここでハッシュ変数(キーと文字列をペアとした変数)を作成します。   上記のコードで   $key{'type'} = 'send';   $key{'name'} = 'user';   $key{'pass'} = 'pwd';   の3つのハッシュ変数が作られています。

sub login { … }
→ サブルーチンです。
  必要に応じて作成します(ここら辺は自分のやりやすいように作りましょう)。

&html('* ユーザ名かパスワードが間違ってます');
→ サブルーチンに引数を渡して呼び出しています。

@msg = @_; → 呼び出されたサブルーチン内ではこのようにして引数を取得します。

次回は簡単な掲示板あたりを作ってみたいと思います。