チャレンジ-レスポンス認証にチャレンジ!
Ajaxでパスワード認証を
ウェブの会員サイトでよくあるパスワード認証にBasic認証というのがあります。ページを開こうとすると、ポップアップが現れてIDとパスワードを要求するあれです。しかし、そのページが認証の必要なページだと分からずに入ってきた人間に、ポップアップはやや不快を与えるかもしれません。また、キャンセル後はキャンセル後で
Authorization Requiredというページに飛ばされ、やはり不快感を覚えるでしょう。そこでBasic認証に限らず、認証方法を画面遷移の伴わない
Ajax化する方法はないかと考えました。
Ajaxでパスワード認証というのは前からあったアイデアのようです
AjaxとPHPを使ったワンタイムパスワード方式のログイン認証
そこで今回
PHPと
JavaScriptを連携させて、少し変わったパスワード認証の仕組みを作ることにしました。また、この認証方法では
SSLは使いません。極力スクリプト(サーバー/クライアント)だけでどうにかできるよう考えた結果、
チャレンジ-レスポンス認証という、パスワードを暗号化して送信する技術があるので、それを代わりに使うことにしました。ただ、そのためにはクライアント側で文字列を暗号化する必要があり、
JavaScript単体で暗号化スクリプトを作らなければなりません。
パスワードの暗号化にはハッシュ関数というのが広く使われており、
MD5、
SHA1などが有名です。ただ、
MD5は異なるパスワードが暗号化でかぶってしまうケースがあることや、最近になって安全性が低下してきたということから主流といわれる
SHA1を暗号化に使うことにしました。
スクリプトは自作する必要がありません。ウェブ上で暗号化スクリプトを提供しているサイトが多くあり、外国だと
Paj’s Home、国内だと
mitsunari@cybozu labsなどで無料で配布されています。私は
mitsunariさんのスクリプトを使わせてもらうことにしました。
なお、パスワードだけ暗号化して送信しても、それを傍受されたら相手がパスワードを知らなくても暗号文をそのまま使われてしまうので、あまり意味がないとありました。そのためにもサーバーと連携したチャレンジ認証が意味を持つようになります。
一方でログイン画面からの画面遷移がないので、ログイン画面=ユーザのアカウントページになり、ログイン画面そのものを作る必要がなくなります。認証前は簡素なログインフォームを用意しておいて、認証が通ったらDOMで一気にページを更新するというやり方になります。
チャレンジ認証のおおまかな流れを順を追っていくと、
1、まずサーバー側がログインページのフォーム要素などに、あらかじめランダムに生成したチャレンジID(現時刻など)を埋め込み、またクッキーに有効期限5分程度でIDを保存しておきます。
2、そしてユーザーがID・パスワードを入力して送信ボタンを押したら、スクリプトでサーバーの送ってきたチャレンジIDと入力されたパスワードを組み合わせて(文字列をただ結合するだけでいいと思いますが)暗号化し、非同期通信でサーバーに送ります。
3、サーバーはユーザーIDとパスワードを受け取ります。このときクッキーを確認して、もし期限切れだったら認証を終了し、ユーザー側にはページを更新し直して再度ログインしてもらいます。クッキーにチャレンジIDが保存されていたら、それを別の変数に移します。また、認証が成功したら念のためクッキーを削除しておきます。
4、そしていよいよパスワードの照合に入ります。サーバー側はチャレンジ値とデータベースに保管していたパスワードを引っ張り出して両者を組み合わせ、クライアント側で行ったのと同じ暗号化を施し、送られてきた(暗号化された)パスワードと突き合わせます。ここでセキュリティ上、注意するところは、クライアント側と同じようにそのまま(平文)のパスワードを暗号化しないと両者の暗号が合わないという点です。つまり、サーバー側ではユーザーのパスワードを、暗号化せずにそのまま保管する必要があるということです。これには何らかの対策が打てるかもしれませんが、ここでは扱いません。
5、パスワード認証が成功したら、セッションを開始してユーザーに会員ページへのアクセスを許可します。ログイン画面はAjaxでそのままホームページにつくり変えます。このとき、おおもとのHTMLを事前に用意しておいて、Ajaxで行うのはコンテナ部分にHTML断片を挿入するだけにするがいいと思います。
問題点としては、そのままのパスワード文をデータベースに保管する必要性から、パスワードの
登録時や
変更時に限って、パスワードの暗号化ができないことです。しかしもちろん、認証時はチャレンジ認証で暗号化されますが。
ともかく、そういうわけで作成したサンプルがこちらです。登録から認証、会員ページまで基本的な流れだけは抑えています。ユーザーIDは日本語でも可です。ID「坂本竜馬」、PASSWORD「12345678」ですでに登録されているので試してみてください。
⇒
画面遷移ゼロのAjax認証
この認証システムは
http://wiz-code.digick.jp/test/ajax_auth/以下に構築されていて、
ログイン認証と登録と会員ページをすべて兼ねたトップページと、
phpフォルダと
jsフォルダからなります。
ajax_auth/
|
―――――――――――――
| | |
index.php php js
phpフォルダは以下の通り
php
|
―――――――――――――――――――――――――――――――――――――――
| | | | | | | |
auth-init auth regi logout member-auth member-main member-regi pager
jsフォルダは以下の通り
js
|
―――――――
| |
member sha1
各ファイルの具体的な説明を次回行いたいと思います。
-
JavaScript/Ajax Ajax, JavaScript, PHP, チャレンジ-レスポンス認証, パスワード認証