最初に
JAVAScript を使用た認証(ログイン)ページを作成しようと思いました。
基本的なプログラムの作成方法を調べるために、google でJAVAScript 認証で検索して見ました。
最初にヒットしたのは、All Aboutでした。
記載の内容を見ると、この手の認証方法に良く見かけるパスワードをファイル名にしているだけの認証とは程遠いやり方でした。
2番目にヒットしたサイトを見てみました。
こちらも全く同じやり方です。
特に私が気に入らないのは、サーバーに Not Found エラーを出させている点です。
一度でもサーバーを構築した人なら、不要なアクセスがどれだけサーバーにとって迷惑であるのかを身にしみて感じていると思います。
まるでスパムロボットのような真似をさせるこのやり方には、正直腹が立ってしまいます。
クライアントサイドで動くJAVAScriptの良さを全く活かしていないではありませんか。
3番目にヒットしたサイトを見てみました。
こちらのサイトでは、ハッシュ関数を使っており、ようやくJAVAScript でのまともな認証方法を行っているようです。
それにしても、日本の著名な解説サイト(google でトップに検索されるようなサイト)では、子供騙し的なやり方しか解説できなくて、まともなやり方は外国のプログラマーの手を借りなければならないのにはがっかりしてしまいます。
プログラムを作成してみる
日本のJAVAScriptを使った認証のやり方の解説では、htmlの中にパスワードを記入している問題外(常識では考えられない)やり方をしているものがあります。
少なくとも、JAVAScript は別ファイルにしなければならないのは、常識中の常識でしょう。
但し、単に別ファイルにしただけでは意味がありませんので、JavaScript をphp で記述します。
例えば、password = 'mypassword' としたいのであれば、外部ファイルは以下のようになります。
<?php header("content-type: text/javascript"); echo "password = 'mypassword';\n"; ?>
これを、password.php とか適当な名前を付けて保存するだけです。
JAVAScript をPHPで動作させるやり方は、テクニックとして昔からある方法ですので説明は省かせていただきます。
初めて耳にされる方は、検索すれば解説はいくらでも見つかりますので御覧になってください。
html はこんな感じになるでしょうか。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html lang="ja"> <head> <meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS"> <title></title> <script type="text/javascript" src="password.php")></script> <script type="text/javascript"> function password_check(){ var pw; pw = document.getElementById('EnterPassWord').value; if(pw != password){ alert("パスワードが違います"); }else{ alert("認証をクリアしました"); //location.href=pw + ".html"; } } </script> </head> <body> <form> <input id="EnterPassWord"type="password" size="20"> <input type="button" value="認証" onclick="password_check();"> </form> </body> </html>
手持ちのHTMLエディターを使用して新規作成で行っておりますので、記入が不要な部分も記載されております。
実際に作成した、動作サンプル を載せておきます。
mypassword を入力すると認証をクリアできます。(ターゲットのファイルには飛ばないようにコメントアウトしています)
これも使い物にはなりませんが、サーバーの迷惑にならないだけ AllAbout の解説よりは増しではないでしょうか。
パスワードもphpで書いておりますので、普通の人は中身は判らないでしょう。
これが使い物にならないのは、1つにはパスワードが判明してしまうと、ログインなどしなくても直接そのファイルをアクセス出来てしまう点にあります。
これでは、何のための認証(ログイン)なのかと言う事になります。
もう1つは、人間が入力するパスワードには限界がある点です。
例えば、パスワードを'h2kR3pNj"などのようにランダムな英数字に設定している人は、まず居りません。
大概は、'pass1234' とか 'apple_suki'とか何かしら意味のある単語にしていると思います。
そうしないと、とても覚えていられないからです。
パスワードをファイル名にしていることがはっきりしているのであれば、良く使われるパスワードを色々と入力してみるだけでも、かなりの確率で見つけられてしまうでしょう。
それで見つけられなかったとしても、プログラムを組んで4文字から10文字ぐらいの英数字で総当たりでファイルを検索すれば、1日も掛からないで探せると思います。
3回間違えると画面を閉じたりすれば多少は長引かせることも可能でしょうが、所詮は時間の問題です。
勿論、通常のファイルでも同様にして探せるのですが、認証を必要とするようなファイルでないものを探す人は居りません。
そもそも、パスワードをファイル名とした認証のやり方は、考え方からして根本的に間違っていると思います。
サイトに載せて解説している人も、それが判っているものだから、この認証方法は簡易的なものだとか、重要な認証には使わないでくださいとか書いておりますが、私から言わせれば使い物にならないような認証方法をなぜ載せるのだと言いたくなります。
驚くのは、JavaScripp の解説サイトの多くが、何の工夫も行うことなく、そっくり真似をしている事です。
誰が最初に考えたのかは知りませんが、人真似好きな日本人の体質を顕著に表していると思います。
認証(ログイン)プログラムに必要なこと
認証(ログイン)プログラムに必要なことをまとめて見ましょう。
(1)プログラムを見てパスワードが判らない事(書くまでもない常識中の常識)
(2)パスワードが判明しても、直接目的のファイル(HTMLファイル)を開けないこと(常識)
(3)間違ったパスワードを入力した場合にサーバーをアクセスしないこと(当然の事)
(4)いったん認証が取れた場合は、他の認証を必要なファイルもアクセスできること(ログインの常識)
(5)認証方法について(認証のやり方)のプログラムを覗かれないこと(当然の事)
(6)他人が使用する場合を考えて、ログアウトが可能なこと(常識)
(7)JAVAScriptがオフの場合でも、異常動作は論外だが何らかの表示をすること(当然の事)
(8)クッキーがオフの環境でもログイン動作に支障がないこと(望ましい)
(9)パスワードの漏洩に備えて、使用者別にパスワードを発行すること(望ましい)
7はJAVAScriptでログインプログラムを作成すると言う前提なので、JAVAScriptがオフの場合には動作しないのは仕方がありませんが、使用者にはその事を伝える必要があります。
8は、クッキーがオフの場合には、次回に自動ログインが出来ないだけで認証系統には差しさわりがない状態を言います。
9は、軽い認証(訪問者全員を対象とするような場合)なら必要がないと思いますが、メンバー制の認証なら必須でしょう。
私が作成したプログラム
ご存知のように私は、自分なりに考えたログインプログラムで実際に運用しております。
本来ならば、そのプログラムを公開して解説すべきなのですが、ログインプログラムの性質上それは出来ません。
やり方を公開すれば侵入は容易になりますので、プログラムの公開は勘弁していただきたいと思います。
その代わり、google で検索して3番目に出てきた方法で作成してみることにします。
後で作成した分、内容はこちらの方がしっかりしています。
このサイトの解説に沿ってやってみたいと思います。
Paul Johnston 氏のサイトのこちらのページにJavaScriptで記述された MD5, SHA-1(いずれも単方向ハッシュ関数のアルゴリズムのひとつ)が公開されておりますので、ダウンロードします。(ライセンスは、BSDライセンスです。)
動作テストを行います。
Input | |
---|---|
Calculate | |
Result |
次にクッキーの動作テストを行います。
上記の Result の内容をクッキーに保存します。
手を抜きたかったので、ささら庵 の解説内容をほぼ丸写しさせていただきました。
要の部分は正常に動作するようですから、最初にログイン画面を作成してみます。
ログインの画面は単調で味気ない画面になりがちですが、個人のサイトのログイン画面は妙な警戒心を抱かれないようにするためにも、できるだけ明るく楽しい画面に工夫するべきでしょう。
私が作成したログイン画面です。
ここでは、サンプルのログイン画面ですから、見飽きないようにと手持ちの色っぽい写真から画像を切り抜いて使いました。(笑)
せつなそうに訴えかけるような目と小さめのおっぱいが気にいっているのですが。(大きいおっぱいも大好きです)
実際に、こんなログイン画面だったら、エロサイトのログイン画面と思われて、ログインする人は誰もいないと思います。
最近は私も鼻の下を長くして画像収集をやっていますので、ウィルスには頻繁に遭遇しますし、感染もさせられました。(笑)
JavaScript のWindowOpen コマンドを使って、640×480で表示させているのですが、ブラウザによって表示状態が異なります。
固定画面の設定(resizable=no)にしても、それが有効に働くのはIEだけのようでしたので、固定画面の設定は解除(resizable=yes に設定)しました。
JavaScriptがオフの場合でも一応表示する(動作はしませんが)ように href にもファイル名を記入しました。
全画面表示にした場合でも、みすぼらしい画面にならないようにバックカラーを入れてあります。
外観やCSSは、私がログインページで使用しているものを、ほぼそのまま使っております。
それも、元はよそ様が作成したコードを、自分用に手直ししただけのものです。
そのため、不必要な部分(使用していない部分)もコードの中に多く残っていると思います。
このように格好の良い入力ページを、自分で1から作成するには荷が重く、膨大な時間が掛かってしまいます。
よそで運用されているものならば、クロスブラウザ対策もなされており、失敗する危険は少なくなります。
著作権の侵害ではないかと言われるでしょうが、私のような技術レベルの低い人間は、人の真似をしないと成長出来ません。
そんな低レベルの書いた解説など、見たくないとおっしゃるのであれば、いつでもお帰りください。
レベルの低い人間が書いているホームページの作成の解説である事は最初にお断りしている筈です。
サブウィンドウを画面の中央に開く
テクニックと呼ぶ程ではありませんが、サブウィンドウを画面の中央に開くためのコードを記載しておきます。
最初にOPENWINDOWをした時に、半分隠れてサブウィンドウが表示されたりしましたので、やり方を調べて対処しました。
厳密に画面の中央には表示されませんが、その必要はないでしょう。
<a href="#" onclick="window.open('login1.html', 'login1', 'width=640, height=480, menubar=no, toolbar=no, scrollbars=no, resizable=yes,left='+(screen.width - 600) / 2+',top='+(screen.height - 480) / 2); return false;">ログイン画面</a>です。
文章の途中で1行の文字リンクで表記したので、見難いかも知れません。
#はVOIDを使うのが正統派のやり方のようです。
return false;は不要だと思いますが、入れておいても弊害はないと思って入れてあります。
IDのlogin1はサブウィンドウをコントロールする予定がある場合は、記入しておく必要があります。(ここでは不要ですが)
画面の中央に表示するためのコードは、left='+(screen.width - 600) / 2+',top='+(screen.height - 480) / 2) の部分です。
やり方も色々ありそうですし、特に説明するまでもない基本的な内容だったかも知れません。
テキストボックスにフォーカスする
これもテクニックと呼ぶ程の内容ではありませんが、知らないと書けません。
フォーカスをあてるには、この場合には document.getElementById('txtPassword').focus(); と書けば良いです。
テキストボックスに何か文字を入れた後にフォーカスするのであれば、続けて document.getElementById('txtPassword').value = "guest"; のように書きます。
他にもやり方はあるかも知れません。
JAVAScriptの記述を隠蔽する
パスワードを生のままで比較するような無茶苦茶な方法をやらないで、ハッシュ関数にして比較するだけでもセキュリティ上はそこそこの状態にはなります。
それでも、どんな方法でパスワードの認証を行っているのかが、明白だといずれは見破られてしまいます。
簡単に見破られないようにするためには、認証部分のJAVAScriptの記述を隠蔽する必要があります。
これには、一番最初に私がサンプルとして記載したように、JAVAScriptをphpで記述するのが最良でしょう。
phpでJAVAScriptを動作させるプログラムも、昔から色々と存在しています。
私は「JavaScriptPacker」と言うPHPでJavaScriptを難読化するプログラムを使用しています。
http://joliclic.free.fr/php/javascript-packer/en/から「packer.php-1.1.zip」をダウンロードできます。
解説サイトもありますし、ダウンロードしたファイルに使用例もありますので、詳しい説明は省きます。
ひょっとしたら、手取り足取り教えなければ理解できない幼稚園レベルの人は使用は無理かも知れません。
せめて私程度(小学校4年生レベル)の知識は必要だと思います。(まだまだ幼稚なレベルですが)
上記のプログラムには、あらかじめphpで変換して使用する事も出来る(そのプログラムが添付されている)のですが、動作時に変換する方式でもストレスを感じるような時間は掛かりません。
私はファイル名も隠蔽できるので、動作時に変換する方式の方を多く使用しています。
これが、どの程度JAVAScriptの記述を隠蔽化できているのかについては、実際にサイトを公開して確かめている状態です。
これが有効であれば、JAVAScriptでもログインのプログラムが作成できると言う事になります。
通常の html の拡張子でプログラムを書くことが可能であれば、使用者に何となく安心感を与えることができるのは確かでしょう。
ここまで情報を提供すれば、その人の才覚でプログラムを作成できると思いますが、具体的なコードを見ないと何もできない方のために、もう少し続けます。
ここからは、単なる一例として提示しているだけです。
使用するハッシュ関数は、SHA-1 を使用しました。
この部分はプログラムの根幹の部分ですから、php で隠蔽化することにします。
その中にパスワードを比較(照合)する部分も一緒に書いておきます。
まず使用するパスワード決めておきます。
本格的に運用するには、パスワードもランダムに発生させて使用者別に分ける必要があるのですが、プログラムが複雑になりますので、ここでは共通のパスワードを作成することにします。
私が実際のプログラムで共通に使用している 'guest' と 'above18' を例にしてやってみましょう。
guest のハッシュ関数は、35675e68f4b5af7b995d9205ad0fc43842f16450 ですから、入力されたパスワードをハッシュ化したものと一致すれば、guest を入力したと判明します。
同様にして above18 は、dbc3b5d17e66a8ea93ab3024cb50c7ee28e3dae2 がハッシュ関数となります。
プログラムの一例は以下のようになります。
function setPassword(){
var out = "";
var sh0 = "35675e68f4b5af7b995d9205ad0fc43842f16450";
var sh1 = "dbc3b5d17e66a8ea93ab3024cb50c7ee28e3dae2";
out = hex_sha1(document.getElementById('txtPassword').value);
if(out == sh0){
out="guest.html";
}else if(out == sh1){
out= sh1.slice(0, 10)+".html";
}else{
out="bad";
}
return out;
}
sh0 にguestのハッシュ、sh1にabove18のハッシュをあらかじめ入れておいて、テキストボックス(id=txtPassword)をハッシュ化したものと比較しています。
一致しなければ、bad が返りますが、guest なら guest.html above ならdbc3b5d17e.html が返ります。
above18 のファイル名をハッシュの前から10文字にして暗号化しているのは、ファイル名で検索されるのを防ぐためです。
パスワードが一致すればファイル名は知られてしまいますが、他のファイル名まで推測されるのは好ましくありません。
ここでは、ファイル名をハッシュの一部を利用していますが、本来はハッシュとは無関係なランダムなものにするべきでしょう。
ターゲットファイルの guest.html や dbc3b5d17e.html を直接アクセスされた場合にオープンしないように対策しなければなりません。
対策と言っても、やり方は簡単でクッキーに保存されている内容をチェックするだけです。
function syogoupw(str){
var pw = "";
var sh0 = "35675e68f4b5af7b995d9205ad0fc43842f16450";
var sh1 = "dbc3b5d17e66a8ea93ab3024cb50c7ee28e3dae2";
pw = ReadCookie("LoginPW");
if(pw == sh0){
if(str>1){location.href="login.html";}
}else if(pw == sh1){
if(str>2){location.href="login.html";}
}else{
location.href="login.html";
}
}
クッキー(LoginPW)にハッシュで保存されているパスワードの内容と照合するだけの単純なものです。
クッキーの中身を覗かれても、ハッシュの内容からパスワードを知ることは困難でしょう。
それから、ターゲットファイルの guest.html や dbc3b5d17e.html はソースの閲覧が容易ですから、パスワード情報は一切載せないようにしなければなりません。
又、ターゲットファイルには重み付けをしなければなりません。
重み付けと言うのは、例えば誰でも閲覧が可能なページのパスワードを guest にしたとします。
それから、成人向けのページはパスワードを above18 にしたとしましょう。
guest でログインした人は、above18 のページを見ることはできませんが、逆は可能にしなければならないと言う様な処理です。
私の場合、最終的なコードは以下のようにしました。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html lang="ja"> <head> <meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS"> <meta name="robots" content="noindex,nofollow"> <title>ログインテスト</title> <script src="sha1.php" type="text/javascript"></script> <noscript> <h1>JavaScript not Active</h1> <meta http-equiv="Refresh" content="3; URL=../index.html"> </noscript> <style type="text/css"> <!-- *{ margin: 0; padding: 0; } html{ margin: 0px; padding: 0px; overflow:hidden; } body{ MIN-WIDTH: 930px; TEXT-ALIGN: center; BACKGROUND-COLOR: #8D1D28 } H1 { color: #fff; } #horizon{ POSITION: absolute; BACKGROUND-COLOR: transparent; TOP: 10px; LEFT: 20px } #horizon{ MIN-WIDTH: 930px; TEXT-ALIGN: center; MARGIN-TOP: -240px; WIDTH: 100%; TOP: 50%; LEFT: 0px } #container{ POSITION: relative; TEXT-ALIGN: left; LINE-HEIGHT: 140%; MARGIN: 0px auto; WIDTH: 930px; FONT-FAMILY:osaka,"MS Pゴシック",sans-serif; BACKGROUND: url(./images/login.jpg) no-repeat; HEIGHT: 480px; COLOR: #fff; FONT-SIZE: 14px } #login-panel{ POSITION: absolute; WIDTH: 640px; TOP: 70px; LEFT: 60px } #please-login{ color: #ffff00; font-weight:bold } BODY#login-password-sent #login-panel{ TEXT-ALIGN: center; WIDTH: 360px; TOP: 190px; LEFT: 290px } #login-panel P{ MARGIN-LEFT: 40px; MARGIN-BOTTOM: 2em } #login-panel A{ PADDING-TOP: 0px; PADDING-RIGHT: 0px; PADDING-BOTTOM: 2px; PADDING-LEFT: 0px; BACKGROUND: url(./images/bg_yellow-dotted.gif) repeat-x left bottom; COLOR: #ffff99; TEXT-DECORATION: none } #login-panel A:hover{ BACKGROUND: url(./images/bg_yellow-solid.gif) repeat-x left bottom } #login-panel H1{ TEXT-INDENT: -9999px; MARGIN-LEFT: 50px; WIDTH: 262px; BACKGROUND: url(./images/hdr_login-to-your-account.gif) no-repeat; HEIGHT: 29px } BODY#login-password-sent H1{ WIDTH: 360px; BACKGROUND: url(./images/hdr_your-password-has-been-sent.gif) no-repeat; HEIGHT: 29px } #login-panel DIV.form FIELDSET{ BORDER-TOP: medium none; BORDER-RIGHT: medium none; BORDER-BOTTOM: medium none; BORDER-LEFT: medium none } #login-panel DIV.form FIELDSET LABEL{ MARGIN: 0px 0px 3px; DISPLAY: block; HEIGHT: 34px } #login-panel DIV.form FIELDSET LABEL#login_email{ } #login-panel DIV.form FIELDSET LABEL#login_email STRONG{ TEXT-ALIGN: right; PADDING-TOP:6px; PADDING-RIGHT: 5px; PADDING-BOTTOM: 0px; PADDING-LEFT: 0px; WIDTH: 68px; HEIGHT: 24px; FONT-WEIGHT: bold; FLOAT: left } #login-panel DIV.form FIELDSET LABEL#login_email INPUT{ BORDER-TOP: medium none; BORDER-RIGHT: medium none; BORDER-BOTTOM: medium none; BORDER-LEFT: medium none; PADDING-TOP: 10px; PADDING-RIGHT: 15px; PADDING-BOTTOM: 0px; PADDING-LEFT: 15px; WIDTH: 188px; HEIGHT: 24px; BACKGROUND: url(./images/bg_login-page-email.gif) no-repeat 0px 0px; FLOAT: left } #login-panel DIV.form FIELDSET LABEL#login_email A{ POSITION: relative; FONT-FAMILY: osaka,"MS Pゴシック",sans-serif; FONT-WEIGHT: bold; TOP: 10px; LEFT: 10px } #login-panel DIV.form FIELDSET LABEL#login_password{ CLEAR: left } #login-panel DIV.form FIELDSET LABEL#login_password STRONG{ TEXT-ALIGN: right; PADDING-TOP: 8px; PADDING-RIGHT: 5px; PADDING-BOTTOM: 0px; PADDING-LEFT: 0px; WIDTH: 68px; HEIGHT: 24px; FONT-WEIGHT: bold; FLOAT: left } #login-panel DIV.form FIELDSET LABEL#login_password INPUT{ BORDER-TOP: medium none; BORDER-RIGHT: medium none; BORDER-BOTTOM: medium none; BORDER-LEFT: medium none; PADDING-TOP: 8px; PADDING-RIGHT: 15px; PADDING-BOTTOM: 0px; PADDING-LEFT: 15px; WIDTH: 190px; HEIGHT: 24px; BACKGROUND: url(./images/bg_login-page-email.gif) no-repeat 0px 0px; FLOAT: left } #login-panel DIV.form FIELDSET LABEL#login_password INPUT#login_submit{ PADDING-TOP: 0px; PADDING-RIGHT: 0px; PADDING-BOTTOM: 0px; PADDING-LEFT: 0px; WIDTH: 71px; HEIGHT: 34px; FLOAT: left } #login-panel DIV.form FIELDSET LABEL#login_remember{ FONT-SIZE: 14px; color: #b00000; PADDING-TOP: 2px; PADDING-BOTTOM: 0px; PADDING-LEFT: 70px; WIDTH: 360px; font-weight:normal } --> </style> </head> <body> <div id="horizon"> <div id="container"> <div id="login-panel"> <div class="form"> <fieldset> <div id="please-login"> <p>We're happy to see you return Please log in.</p> </div> <label id="login_email"> <strong>Email</strong> <input name="txtLoginEmail" type="text" id="txtLoginEmail" value="example@example.com"> </label> <label id="login_password"> <strong>Password</strong> <input name="txtPassword" type="password" id="txtPassword"> <input src="./images/btn_log-in-alt.gif" onclick="setPassword();return false" type="image" id="login_submit" tabindex="3" alt="Log-in"> </label> <label id="login_remember"> <input name="chbRememberMe" type="checkbox" id="chbRememberMe"> Remember me on this computer </label> </fieldset> </div> </div> </div> </div> </form> <script type="text/javascript"> CheckPW_init(); </script> </body> </html>
記載内容を見易いようにスタイルシートも一緒に記入しています。
普通と変わっている点と言えば、JavaScriptがオフの場合にmetaタグでindex に飛ばしている点でしょうか。
一般的には(解説プログラムの多くは)、ここはJavaScriptがオフですとか、コメントを出すだけにしているのが大部分です。
ログインファイルのようなセキュリティを要求されるものは、できるだけソース内容が目に触れにくいようにしたいものです。
JavaScriptをsha1.phpのようにphpで動作させているのは前述したように、プログラムコードの難読化(隠蔽)のためです。
パスワードをハッシュの状態で認証するのは当然でしょうが、JavaScript自体も内容は簡単に見る事が出来ないようにしています。
ターゲットのファイルも認証を行わないで直接アクセスした場合には、ログインプログラムに飛ばすようになっています。
コードは以下のようにしています。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html lang="ja"> <head> <meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS"> <title>guestページ</title> <script src="sha1.php" type="text/javascript"></script> <noscript> <meta http-equiv="Refresh" content="0; URL=../index.html"> </noscript> </head> <body> <script type="text/javascript"> syogoupw(1); </script> <noscript> <img src="./images/white.jpg" alt=""> </noscript> guestページです。<br> <a href="#" onclick="DeleteCookie('LoginPassword')";>ログアウト</a><br> </body> </html>
syogoupw(1)の部分が、ログインを通っているのかどうかの判定を行う部分です。
ハッシュで認証していると言っても、html(ソース)を見る限りでは全くそれが判りません。
javascriptで動作させているのは判りますが、その処理内容までは判らないでしょう。
念を入れたければ、このhtmlファイルを暗号化するのも良いと思います。
この程度は当たり前の事なのですが、日本でJavaScriptで書いたログインプログラムの解説サイトはそのようにしておりません。
書いてある事と言えば、どれもこれもJavaScript はセキュアな言語ではないとか、簡易的だとか他人の書いた内容の丸写しばかりです。
そこそこのレベルのプログラマーが書いているのでしょうが、私のようなプログラムの素人でも泣けてきます。