HTTP 基本認証の行われかた
SPECIAL
基本認証 (BASIC 認証)
HTTP でユーザアカウントによってアクセスを制限する仕組みのひとつである 基本認証 はどのような仕組みでやり取りされているのかを調べてみようと思います。
この基本認証。パスワードが暗号化されずに送られるので盗聴されやすいとかはあるのですけど、何はともあれ取り扱いやすいはずです。実装がしやすければ、ブラウザからコントロールできるちょっとした管理ツールなんかを作れそうですよね。
もっともそんなツールは、Apache と CGI を使って作った方が楽そうな気もするのですけど^^;
認証の流れ
Windows XP Professional の IIS を用いて基本認証が必要な仮想ディレクトリ /AuthTest/ を用意して、一連の流れを TELNET にて確認してみました。
HTTP リクエストを発行してみる
C:\telnet localhost 80
GET /AuthTest/index.html HTTP/1.0
上のようにBASIC 認証が設定された Web サイトに対して通常のリクエストを行うと、Web サーバは認証が必要とのことを示すステータス 401 を返してきます。
HTTP/1.1 401 Access Denied
Server: Microsoft-IIS/5.1
Date: Tue, 29 Jul 2003 06:40:34 GMT
WWW-Authenticate: Basic realm="EZ-NET"
Content-Length: 4395
WWW-Authenticate: Digest qop="auth", realm="EZ-NET", nonce="a0888b67c....b1289"
Content-Type: text/html
上記は返してきたヘッダの部分です。
先頭行の "HTTP/1.1 401 Access Denied" にて、認証が必要であることが通知されています。
そして WWW-Authenticate: Basic realm="EZ-NET" という部分が基本認証が必要ということを示しています。ここの "realm=" の部分が、一般ブラウザで認証ダイアログに表示されるテキストです。
もうひとつ WWW-Authenticate: Digest qop="auth", realm="EZ-NET", nonce="..........." なる行がありました。これはダイジェスト認証もサポートしている…ということでしょうか。ダイジェスト認証の方はとりあえず後回しにしますけど、それほどの手間がかからないようだったらこちらもサポートしたものを作れるかもしれないですね^^
認証してみる
さて、ステータス 401 をもらってしまっては目的のページは表示されません。
が、返されたメッセージの中にどのような認証をサポートしているかが記されているため、それを頼りに今度は認証を行ってみます。認証には Authorization: ヘッダを付加して行います。ここへ認証方式と、それに必要な情報をあわせて送信します。
基本認証の場合、ユーザ名とパスワードを base64 エンコードしたものを渡します。ユーザ名とパスワードは、間にコロン ( : ) をはさんだものを1文としてエンコードします。
base64 エンコードに関しては EZ-NET : Base64 の仕組み あたりを参考にしてみてください。
GET /AuthTest/index.html HTTP/1.0
Authorization: Basic QXV0aFRlc3Q6cGFzc3dvcmQ=
認証に成功すると、通常通りの応答が返ってきます。
認証ページのリンクをたどる
さて HTTP は基本的には 1 ページの要求ごとに完結します。なので認証は一回パスしても次ぎのページを表示しようとする際には再び行わなければいけないはず…。
当然ながらキープアライブではない状態ならば、サーバ側はそのクライアントが既に認証をパスしたかどうかを知る術はありません。なのでこちらは Authorization: ヘッダを毎回つけるのが自然でしょう。
なにはともあれ index.html ページにて a.html へリンクをはり、その2つを連続して要求してみることにします。
キープアライブを利用しない場合
確認も何もないような気がしますけど念のため実験してみました。
GET /AuthTest/index.html HTTP/1.0
上のように要求すると、当然ながらステータス 401 が返されるので、再び認証リクエストを行います。
GET /AuthTest/index.html HTTP/1.0
Authorization: Basic QXV0aFRlc3Q6cGFzc3dvcmQ=
これで a.html へリンクがはられたページデータを取得…。いや、リンクがはられていようがいまいが、Web サーバは振る舞いはなんら変えないでしょうけれど。
そして続けて a.html を要求してみます。
GET /AuthTest/a.html HTTP/1.0
するとこちらも、ステータス 401 が返されました。改めて Authorization: ヘッダをつけて要求するとちゃんとしたデータが取得できます。
以上から、少なくともキープアライブではな状態では、認証ヘッダーを毎回つけて要求する…、サーバ側の立場から言うならば、Authorization: ヘッダーがないならば 401 を返す必要があるようでした。
キープアライブを利用する場合
さて、基本 1 ページ単位での取り扱いとなる Web サーバですけど、かろうじてクライアントが同一であるかを知ることが出来るものにキープアライブがあります。
Cookie とかを利用しても一応は把握できますけど、キープアライブならば 1 ページごとに接続をきるということがないので、これならサーバ側でもかろうじて認証情報を維持できる可能性がある…ということで実験です。
手続きは上記の場合とまったく一緒です。ちょこっとちがうのが、最初の一行目の HTTP/1.0 の部分を HTTP/1.1 にしています。また HTTP/1.1 の場合は仮想ドメインのための Host: ヘッダが必須のようなので、そちらも付加してあります。
GET /AuthTest/index.html HTTP/1.1
Host: localhost
上のように要求すると、当然ながらステータス 401 が返されるので、再び認証リクエストを行います。このとき、キープアライブが有効になっているため、Web サーバとの接続が切断されません。
GET /AuthTest/index.html HTTP/1.1
Host: localhost
Authorization: Basic QXV0aFRlc3Q6cGFzc3dvcmQ=
これで a.html へリンクがはられたページデータを取得…。そして続けて a.html を要求してみます。
GET /AuthTest/a.html HTTP/1.1
Host: localhost
すると、今度は Authorization: ヘッダを付加することなしにページを表示することが出来ました。
キープアライブを利用すると認証は初回の 1 度だけでいいようですね。なるほどこれならたしかに合理的だし、プログラミング的にもこちらの方が何かと都合がよさそうですね^^