セッション管理

yahoo, google, twitter, amazon... 今はどこのサイトもログインしてそのユーザ専用ページが表示されるようになっている。 前からこの仕組みをやってみたいと思っていた。 idとパスワードを入力させて、それをデータベースで参照して正しければ認証する。 実際は暗号化したり、SQLとかを使っているのだろうが、 原理だけを確認するなら、その辺は平文でテキストファイルでよい。

テキストボックス2つとボタンを作って、postさせれば認証機能は実現できる。 しかし問題はその先である。 単純に考えるなら、



  1. OKなら ok.htmlを表示し、NGなら ng.htmlを表示する。

  2. OKなら"ok"を、NGなら"ng"を引数としてauth.cgiを呼び、引数に応じて「ようこそ」「認証できません」などと表示する。

しかし問題なのは、認証の可否をどこかに維持しておかなければならないということだ。 それを「セッション管理」といって、perlにも CGI:Session というモジュールがある。 それを使えばいいのだろうが、複雑で、mySQLなどもからんでいてメンドクサイ。 もっと単純にできないだろうか? IPアドレスで管理するのはどうだろうか? いったんIDとパスワードを認証したら、そのときのuserのIPアドレスと、認証がOKであることを、ファイルに記録しておく。 サイトでは常にそのファイルを参照するようにして、認証されているかどうかに応じてページの表示を変える。 多分、「セッション管理」とか言うのも、同じようなことをしているはずだ。あとはポート番号を見たり、認証した時間を記録しておいて一定時間がたったらタイムアウトさせるとか・・・ でもあれか、natしてたりしたらIPアドレスで管理したら全部同じになっちゃうな。 セッションIDというのはHTTPプロトコルの仕組みで、それをサーバとクライアント(ブラウザ)で保持するようだ。だが、パケットキャプチャしても"session id"みたいなフィールドが見つからない。

セッション管理というのは、ステートレスであるHTTPプロトコルで状態管理をさせるための苦肉の策のようだ。セッションIDを生成して、それをクッキーを使ってクライアントに渡す。

#!/usr/bin/perl

use CGI;
use CGI::Session;

my $cgi = CGI->new;
my $session = CGI::Session->new(undef, $cgi, {Directory=>'./tmp'});
session->param('name','mysession');

print $session->header(-charset=>'UTF-8');

print   $cgi->start_html(-lang=>'ja', -encoding=>'UTF-8', -title=>'http session test'),
$cgi->p('session id: '.$session->id.'<br/>',
'name: '.$session->param('name').'<br/>'),
$cgi->end_html;


とりあえずこのようなcgiを作って実行すると、session idが表示される。F5を押すたびにidは変わる。パケットキャプチャしてみると

Set-Cookie: CGISESSID=5d6b6c1c3248aa9b399060dcef4c4e58; path=/


のように、セッションIDがサーバからクライアントに返す HTTP OKのパケットの中に入っているのがわかる。・・・・・・で?

まずはcookieからだな。 cookieというのは、サーバ側から送信するもので、ユーザが閲覧するとユーザがcookieを無効にしていない限り勝手に保存される。 cookieには名前、値、ドメイン名、パスなどが設定できる。 ユーザが保存しているcookieは、環境変数

$ENV{'HTTP_COOKIE'}


で取得できる。 たとえば「名前」=「アクセス日時」というcookieを送信しておけば、次のアクセス時に「前回のアクセスは何月何日でした」などと表示できる。

amazon.co.jpにアクセスしたら、6個のcookieが保存された。

at-acbjp
session-id
session-id-time
session-token
ubid-acbjp
x-acbjp


値を見てもなんのことやらさっぱりわからないが、 サインインしたときにアカウントと関連付けて保存しておけば、どのアカウントかわかる。 どのサイトでも「ログインしたままにする」などのチェックボックスがついているが、 それをチェックしたときはcookieを見てアカウントの認証プロセスを飛ばすのだろう。 と、こう見てくるとperlの CGI::Session モジュールがやってることはたいしたことがないように思えてきた。 ただidを発行してcookieにセットしてるだけじゃないのか?




パソコンに写真がたくさん溜まってきて、特に見ないのだが捨てるのももったいなくてとってある。 これをwebに置くことにした。 いろいろあるけど、picasaのwebアルバムに落ち着いた。 いったん上げてしまうと、フォルダの階層が作れなかったり、削除や移動が一度にできなかったりとメンドクサイが、大量ファイル操作は一度ダウンロードして操作してアップロードするなどしている。それにしても重複ファイルの多いこと・・・メニューの「整理」を選ぶと、複数選択して削除や移動ができる。天下のgoogleがそんなことくらいできないわけないよな・・・