Perlで、セッション管理をする(CGI::Session,CGI::Cookie,MySQL使用)

Perlで、パスワードをハッシュ化してユーザー情報を管理する - undiscoの日記の続きです。

セッション管理というか、セッションIDを吐いてCookieに記録するだけです。
ユーザーIDとパスワードの認証後に実行します。

CGI::SessionとCGI::Cookieを使用し、セッションIDはMySQLへ保存します。

今回は、http://www.yamareco.com/ippiki/detail.php?mid=25&mver=0Tutorial - CGI::Sessionのさらに広範囲に渡って記述されたマニュアル - perldoc.jpを参考にしました。

ユーザー名とパスワードを入力するsignin.html、ユーザー認証処理と、セッションIDを吐いてCookieに記録するsignin.plと、ページ遷移してセッションIDをCookieから読み取り表示するsession.plからなります。

  • DB定義
CREATE TABLE sessions (id CHAR(32) NOT NULL UNIQUE, a_session TEXT NOT NULL) ENGINE=MyISAM DEFAULT CHARSET=utf8;
  • signin.html
<html>
<head>
<title>ユーザー認証フォーム</title>
</head>
<body>

<form name="form" action="./signin.pl" method="post">
user_name:<input type="text" name="user_name">
password:<input type="password" name="password">
<input type="submit" name="submit" value="認証">
</form>

</body>
</html>
  • signin.pl
#!/usr/bin/perl

use strict;
use warnings;
use CGI;
use CGI::Session;
use CGI::Cookie;
use DBI;

##user_testデータベース名/ユーザー/パスワード
my $db_name='user_test';
my $db_user='user_db';
my $db_passwd='user_pass';
my $db_host='127.0.0.1';

##フォームからのパラメタ取得
my $q = new CGI;
my $user_name = $q->param('user_name') || '';
my $password = $q->param('password') || '';
my $url='./signin.pl';

##ユーザー情報の抽出
#DB処理
    my $db = DBI->connect("dbi:mysql:dbname=$db_name","$db_user","$db_passwd",{RaiseError=>0,AutoCommit=>1}) || &print_error(" データベースへの接続に失敗しました。<br>\n");
    my $sql="SELECT user_name, password FROM user WHERE user_name = '$user_name'";
    my $st = $db->prepare($sql);
    my $res = $st->execute;
    my($db_username, $db_password) =  $st->fetchrow_array();
    $st->finish;
    $db->disconnect;

##ユーザー名とパスワードのチェック
    my $flag = 0;
    my $sid;
    if(($db_username ne '') and ($user_name eq $db_username) and ($db_password eq crypt($password, $db_password )))
    {
        $flag = 1;
        #ヘッダ
        my $dbh = DBI->connect("dbi:mysql:dbname=$db_name","$db_user","$db_passwd",{RaiseError=>0,AutoCommit=>1}) || &print_error(" データベースへの接続に失敗しました。<br>\n");
        $sid = $q->cookie("CGISESSID") || undef;
        my $session = new CGI::Session("driver:MySQL", $sid, {Handle=>$dbh});
        $sid = $session->id();
        my $cookie = $q->cookie(-name    => "CGISESSID",
                                -value   => $session->id,
                                -expires => "+1d");
        print $q->header( -cookie=>$cookie, -charset=>'Shift_JIS');
    }else{
        #ヘッダ
        print $q->header( -charset=>'Shift_JIS');
    }

##HTML記述
print <<HEAD;
<html>
  <head>
	<meta http-equiv="content-type" content="text/html; charset=shift_jis"/>
	<title></title>
  </head>
  <body>
HEAD

##BODY内記述
    if($flag)
    {
        print "ユーザー$db_usernameでログインしました<br>";
        print "セッションIDは$sidです<br>";
        print '<a href="./session.pl">ページ遷移してsidを確認</a>';
    }else{
        print "ユーザー名またはパスワードが違います";
    }

print <<FOOT;
<br><br><br>
</body>
</html>
FOOT

sub md5hash()
{
    my $pass_org = shift;
    srand();
    my @salts = ( "A".."Z", "a".."z", "0".."9", ".", "/" );
    my $salt = $salts[int(rand(64))] . $salts[int(rand(64))];
    return crypt($pass_org, '$1$' . $salt);
}
  • session.pl
#!/usr/bin/perl

use strict;
use warnings;
use CGI;
use CGI::Session;

##フォームからのパラメタ取得
my $q = new CGI;

##ヘッダ、HTML記述
print "Content-type: text/html\n\n";
print <<HEAD;
<html>
  <head>
	<meta http-equiv="content-type" content="text/html; charset=shift_jis"/>
	<title></title>
  </head>
  <body>
HEAD

##セッションIDの取得、表示
    my $sid = $q->cookie("CGISESSID") || undef;
    if($sid)
    {
        print "セッションIDは、$sidです";
    }else{
        print "セッションIDはありません";
    }

print <<FOOT;
<br><br><br>
</body>
</html>
FOOT