まずはサンプルを見てください。認証の例: http://X68000.q-e-d.net/~68user/net/sample/http-auth/secret.html上記 URL をクリックすると、以下のような認証画面が表示されます。
(ユーザ名: hoge、パスワード: fuga で閲覧できます)
IE6 の認証画面 Mozilla の認証画面
ここで正しいユーザ名・パスワードを入力するとファイルを閲覧できます。 間違ったユーザ名・パスワードを入力すると、上記の認証画面が何度でも表示されます。 もしキャンセルボタンを押すと、以下のような画面が表示されます。
![]()
まずは telnet で http://X68000.q-e-d.net/~68user/net/sample/http-auth/secret.html にアクセスして、どのような仕組みになっているのかを確認しましょう。% telnet X68000.q-e-d.net 80 GET /~68user/net/sample/http-auth/secret.html HTTP/1.0 (リターン) Host: X68000.q-e-d.net:80 (リターン) (続けてリターン) HTTP/1.1 401 Authorization Required Date: Fri, 03 Dec 2004 15:43:35 GMT Server: Apache/2.0.52 (FreeBSD) WWW-Authenticate: Basic realm="Secret File" Content-Length: 491 Connection: close Content-Type: text/html; charset=iso-8859-1 <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"> <html><head> <title>401 Authorization Required</title> </head><body> <h1>Authorization Required</h1> <p>This server could not verify that you are authorized to access the document requested. (略)以下の 3点に注目してください。ブラウザはレスポンスコード 401 が返ってくると「認証が必要なページである」と判断し、 ユーザ名・パスワード入力のためのウィンドウを表示するわけです。
- サーバが返すレスポンスコードが 401 となっている。
- サーバが WWW-Authenticate: Basic realm="Secret File" というヘッダを返している。
- ボディ部の HTML は、認証画面でキャンセルボタンを押したときの表示と同じ。
認証方法にはいくつかの種類があります。例えば Basic 認証と Digest 認証があります (と言っても、それ以外の認証方法を当ページ管理人は知りませんが)。 この例では
WWW-Authenticate: Basic realm="Secret File"というヘッダが示すとおり、サーバ側は Basic 認証を要求しています。「Basic 認証」は、「基本認証」「ベーシック認証」と言うこともあります。 なぜ Basic 認証という名前になったかというと、おそらくは最もシンプルで基本的な認証方法だったからでしょう。Basic 認証において、ユーザ名とパスワードを送信する方法を説明します。まずユーザ名とパスワードをコロンで結合します。 もしユーザ名「hoge」、パスワード「fuga」の場合、「hoge:fuga」という文字列を作るわけです。 それを BASE64 でエンコードします。 「hoge:fuga」を BASE64 エンコードすると「aG9nZTpmdWdh」となります。
UNIX のコマンドでは、以下のようにして確認できます。% echo -n 'hoge:fuga' | base64 -e % echo -n 'hoge:fuga' | openssl enc -e -base64 % echo -n 'hoge:fuga' | nkf -MB % echo -n 'hoge:fuga' | perl -MMIME::Base64 -ne 'print encode_base64($_)'参考:「UNIX の部屋」 base64 ・ openssl ・ nkf上記の Perl の例では MIME::Base64 モジュールを使っていますが、 Perl-5.8 以降であれば標準でインストールされています。 それ以前の Perl であれば適当にインストールしてください。
さきほどのコネクションは既にサーバ側から切断されていますので、 再度 web サーバに接続します。 このとき、
Authorization: Basic (BASE64 エンコードしたユーザ名とパスワード)というヘッダを送ります。
% telnet X68000.q-e-d.net 80 GET /~68user/net/sample/http-auth/secret.html HTTP/1.0 (リターン) Host: X68000.q-e-d.net:80 (リターン) Authorization: Basic aG9nZTpmdWdh (続けてリターン) HTTP/1.1 200 OK Date: Fri, 03 Dec 2004 16:42:56 GMT Server: Apache/2.0.52 (FreeBSD) Content-Length: 176 Content-Type: text/html; charset=euc-jp <html> <head> <META HTTP-EQUIV="Content-Type" Content="text/html; charset=EUC-JP"> <title>ひみつのファイル</title> </head> <body> これは秘密ファイルです。 </body> </html>認証で保護されているファイルを見事に取得できました。では、誤ったユーザ名・パスワードを送るとどうなるか試しましょう。
% telnet X68000.q-e-d.net 80 GET /~68user/net/sample/http-auth/secret.html HTTP/1.0 (リターン) Host: X68000.q-e-d.net:80 (リターン) Authorization: Basic aaaaa ●誤ったユーザ名・パスワードを送信 (続けてリターン) HTTP/1.1 401 Authorization Required WWW-Authenticate: Basic realm="Secret File" (略) <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"> <html><head> <title>401 Authorization Required</title> </head><body> <h1>Authorization Required</h1> <p>This server could not verify that you are authorized to access the document requested. (略)興味深いことに、Authorization ヘッダを付けないときと全く同じレスポンスが返ってきました。
適当なページを探して、一番最初のリクエストで Authorization ヘッダを送信してみてください。 つまり、サーバにレスポンスコード 401 を返させることなく、 初めから Authorization ヘッダを付けてリクエストしてください。 ユーザ名・パスワードが正しければ、ちゃんとページを取得できるはずです。また、一度 Authorization ヘッダを付けて認証を通った後に、 Authorization ヘッダなしでリクエストを送ってみてください。 やっぱりレスポンスコード 401 が返ってきてしまいます。
つまり、web サーバが行っていることは、
これだけです。
- 認証が必要なページに Authorization ヘッダなしでリクエストしてきた場合、401 を返す
- 認証が必要なページに Authorization ヘッダ付きでリクエストしてきた場合、 (ユーザ名・パスワードが正しければ) ページ内容を表示する
認証が必要なページを取得する場合は、リクエストごとに毎回 Authorization ヘッダを送信する必要があります。HTTP の認証には、ログイン・ログアウトというような概念がないのです。 これはしっかりと認識しておいてください。
ログイン・ログアウトの概念はありませんが、以下のような CGI プログラムを使うことで、 疑似的にログアウトすることもできます (訪問者に、認証画面でキャンセルボタンを押してもらう必要があるので、 かなり無理がありますが)。#!/usr/local/bin/perl print <<END; Content-type: text/html Status: 401 Authorization Required WWW-Authenticate: Basic realm="Secret File" <html><head><title>401 Authorization Required</title></head> <body><h1>Authorization Required (by CGI)</h1></body></html> END
Basic 認証はシンプルな認証方法という利点があります (そのおかげで、 早い時期からほぼ全ての web サーバ・ブラウザに実装されていました)。 しかし「盗聴に弱い」という大きな弱点があります。 tcpdump や ethereal などでパケットをダンプしてしまえば、Authorization: Basic aG9nZTpmdWdhというヘッダは簡単に得られます。これを Base64 デコードすれば「hoge:fuga」が手に入ります。 セキュリティもへったくれもないですね。Base64 エンコードは暗号化ではありません。ただのコード変換です。 鍵のない変換を暗号化とは呼びません。
今回のサンプルで使用した認証関連の設定ファイルは以下の通りです。 Apache の初期設定では、「.ht」から始まるファイルを閲覧できないようになっていますApache の設定ファイル httpd.conf に以下のように記述されているはずです。このサンプルでは、この制限を外すよう .htaccess にて設定していますが、 普通はこういうことはしません。また、パスワードファイルを public_html 以下に置くのもお勧めできません。<Files ~ "^\.ht"> Order allow,deny Deny from all </Files>
- .htaccess
apache 設定ファイル。.htaccess と .htpasswd を公開するため、allow from all としている。- .htpasswd
パスワードファイル。以下のようにして作成したもの (ユーザ名: hoge、パスワード: fuga)。% htpasswd -c .htpasswd hoge New password: (fuga と入力) Re-type new password: (fuga と入力) Adding password for user hoge- secret.html
秘密のファイル (ユーザ名: hoge、パスワード: fuga)
$Id: http-auth-1.html,v 1.7 2005/03/11 15:34:45 68user Exp $