Cookie を使ったユーザー認証を JavaScript で実装する
今日は、なぜか JavaScript でユーザー認証を実装する方法をご紹介します。いや、都合で必要になったもので、ついでに記事にしただけです(^^ヾ。もちろん JavaScript ではクラックしようと思えばいくらでもできてしまうのですが、「あまりやられたくない」程度のことを防御する手段としては便利なのではないでしょうか。
認証は、入力したパスワードを Cookie に保存しておき、ページ内に暗号化して埋め込んだパスワードと比較することで行います。JavaScript で Cookie を扱ったりパスワードを暗号化したりする方法は、他にも応用できると思います。
Cookie の設定
ではまず、Cookie の設定方法からご紹介します。JavaScript で Cookie を設定するには、document.cookie に Cookie の文字列を代入します。書式は HTTP リクエストヘッダの Set-Cookie と同じです。同じ名前の Cookie があれば上書きしますが、他の名前の Cookie に影響はありません。このあたり、後述の document.cookie の読み出しに対して機能に線形性がないのが美しくありませんよねぇ・・・。本来はメソッドで実装するべきではなかったかと。ま、言語仕様なので仕方ありません。
以下、Cookie を設定する関数のサンプルです。
function SWSetCookie(name, value, expire, path) { var cookie = name + '=' + escape(value); if(expire) { cookie += '; expires=' + expire.toGMTString(); } if(path) { cookie += '; path=' + path; } document.cookie = cookie; }
Cookie の取得
設定方法がわかったら次はもちろん取得方法です。document.cookie の値を読み出すと HTTP レスポンスヘッダの Cookie と同じ文字列が取得できます。全ての Cookie がひとつの文字列で返されますので、その中から目当ての Cookie 名を検索し、その値を切り出さなければなりません。具体的には、以下のようにするのが定番です。
function SWGetCookie(name) { var cookie = document.cookie; if(cookie && cookie.length > 0) { var offset = cookie.indexOf(name + '='); var end; if(offset != -1) { offset += name.length + 1; end = cookie.indexOf(';',offset); if(end == -1) { end = cookie.length; } return unescape(cookie.substring(offset,end)); } } return ""; }
パスワードの暗号化
これで Cookie の取得・設定はできるようになりましたので、これだけでも簡単なパスワード認証はかけられます。しかし、単純に実装すると JavaScript のソースのなかに生のパスワードを埋め込む必要があり、簡単にパスワードがばれてしまいます。それを防ぐために、ここでは単方向ハッシュ関数というものを使います。
単方向ハッシュ関数とは
単方向ハッシュ関数とは、任意長のデータ列を固定長のデータ列に変換する関数で、変換後のデータから変換前のデータを推測することが極めて難しいものを言います。この性質を利用して、JavaScript のソースには変換後のデータを埋め込んでおき、Cookie から取得した文字列を同様に変換した結果が等しければユーザーとして認証するようにします。こうすれば、ソースに埋め込まれるデータからパスワードを割り出すことは困難であるため、パスワードの秘匿性が守られます。
JavaScript で単方向ハッシュ関数を計算する
残念ながら、JavaScript の標準機能にはこの単方向ハッシュ関数を計算する機能がありません。そこで少し探してみたところ、Paul Johnston 氏のサイトのこちらのページに JavaScript で記述された MD4, MD5, SHA-1(いずれも単方向ハッシュ関数のアルゴリズムのひとつ)が公開されていました。ここでは、最も強度が高い SHA-1 を使おうと思います。使い方は簡単、配布されている sha1.js をインポートし、変換する文字列を hex_sha1 関数に渡せば、変換後の固定長文字列が返ります。
var hashed = hex_sha1('password');
なお、MD4, MD5 にはすでに脆弱性が発見されています。今回のような使い方なら現時点では簡単には破られないと思いますが、念のため SHA-1 を使っておきましょう。
認証してみる
それでは、実際にユーザー認証をしてみましょう。前述の SWSetCookie, SWGetCookie, sha1.js がすでに使える状態になっているとして、以下のような HTML で認証が実現できます。
<script type="text/javascript" language="JAVASCRIPT"> <!-- function SWAuthUser() { var password = '5925f290d8a86e06fa6d3f609a22ceb09b332768' var value = document.getElementById('sw_password').value; if(hex_sha1(value) == password) { document.getElementById('sw_result').innerHTML = '認証しました!'; } else { document.getElementById('sw_result').innerHTML = 'パスワードを入力してください'; } SWSetCookie('sw_javascriptauth_password', value); } // --> </script> <input id="sw_password" type="password"></input> <input id="sw_button" type="button" value="Send" onClick="SWAuthUser();"></input> <div id="sw_result"></div> <script type="text/javascript" language="JAVASCRIPT" defer="defer"> <!-- document.getElementById('sw_password').value = SWGetCookie('sw_javascriptauth_password'); SWAuthUser(); // --> </script>
以下のフォームは上記のスクリプトをそのまま入力したものです。パスワードとして「GentooLinux」と入力し、「Send」ボタンを押すと、下の表示が「パスワードを入力してください」から「認証しました!」に変化します。パスワードは Cookie に記録されますので、ページをリロードしても認証が通ります。なお、このCookie はブラウザを終了すれば綺麗さっぱり消えますので、ご安心ください。
JavaScript がクライアント側で動作する関係上、どこまでやってもセキュアにはならないのですが、それなりの手間を設定してクラックする意欲を削ぐという効果はあります(^^;。自分のサイトで自分に対してだけは特定のスクリプトを動作させたい(もしくは動作させたくない)なんてときには、けっこう便利に使えるのではないでしょうか。
詳しくはこちらの記事をどうぞ!
この記事にコメントする