Basic 認証を使う
Web サイトを作っていると、「このディレクトリ以下は公開せずに、自分だけがアクセスできるようにしておきたい」と思うことが多々あります。それを実現する簡単な方法として HTTP プロトコルで既定されているのが Basic 認証です。この方法は平文でパスワードを送信するのであまりセキュアではありませんが、さほど機密性の高くないデータを保護するのには便利です。とくに安価なレンタルサーバーでは、認証機構を自分で実装しない限りはこれしか選択肢がなかったりすることもあります。というわけで、本日はこの Basic 認証についてご紹介しようと思います。
Basic 認証の基本的な使い方はいろいろなサイトで紹介されているので、言及されることの少ないグループ機能や htpasswd コマンドのいろいろな使い方などを含めてみました。とりあえず自分ひとりの認証にしか使ったことがないという方、これを機にもう少し高度な使い方も把握してみてはいかがでしょうか。
とにかく使ってみる
まずは、概要を掴むために、とにかく設定してみましょう。例として、 "/var/www/localhost/htdocs" というディレクトリへのアクセスを制限する方法をご紹介します。
最初にアクセス可能なユーザーとそのパスワードを管理するファイルを作成する必要があります。以後、このファイルを「パスワードファイル」と呼びます。パスワードファイルの作成は htpasswd コマンドを使って行います。パスワードファイルの場所やファイル名は、 Apache がアクセス可能であればなんでもかまいませんが、 Web ブラウザからアクセス可能な公開ディレクトリには置かないでください。認証の意味がなくなります(^^;。ここでは、パスワードファイルは "/var/www/localhost/passwd" とします。パスワードファイルを新規作成し、そこに "hokousya" ユーザーを追加するには、以下のコマンドを実行します。
htpasswd -cm /var/www/localhost/passwd hokousya
コマンドを実行すると、パスワードを 2 回尋ねてくるので、同じパスワードを入力してください。
なお、GentooLinux では htpasswd コマンドは htpasswd2 という名前になっています。さらに "usr/sbin" にあるので、一般ユーザーではパスが通っていない可能性がありますのでご注意ください。 "/usr/sbin/htpasswd2" という風にフルパスで指定すれば、一般ユーザーでも実行できます。
パスワードファイルを作成したら、今度はアクセス制限をかけるディレクトリを設定します。そのためには、該当ディレクトリに ".htaccess" というファイル名で以下の内容を記述します。今回の場合は "/var/www/localhost/htdocs/.htaccess" ですね。
AuthType Basic AuthName "Local host" AuthUserFile /var/www/localhost/passwd Require valid-user
ここまで設定したら、 Web ブラウザで該当ディレクトリにアクセスしてみてください。以下のように認証ダイアログが表示されるはずです。
ここで「ユーザー名」と「パスワード」に htpasswd コマンドで設定したものを入力して「OK」ボタンをクリックすれば、はれてアクセスが許可されます。もし正しいユーザー名やパスワードを入力しないと「Authorization Failed」というエラーになるはずです。ちなみに、一度認証したユーザー名とパスワードはブラウザを終了させるまで保存されるので、 2 回目からは認証ダイアログは表示されません。別のユーザーでログインしたい場合はブラウザを終了させる必要があります。
もし最初から認証ダイアログが表示されず無条件でアクセスできてしまう場合は、 Apache の設定で ".htaccess" による認証の設定が許可されていないことが考えられます。Apache の設定ファイルに以下の記述を追加してください。
<Directory "/var/www/localhost/htdocs"> # 他の設定 AllowOverride AuthConfig </Directory>
AllowOverride は ".htaccess" で上書きできる設定を指定するディレクティブです。詳細は Apache のドキュメントをご覧ください。
ディレクティブの詳細
Basic 認証に関連する Apache 設定ファイルのディレクティブは以下のとおりです。
- AuthType <type>
- 認証方法を指定します。現在のところ、type に指定できるのは "Basic" (パスワードをプレーンテキストで送信)と "Digest" (暗号化して送信する)のみです。今回は "Basic" を指定した場合のみを扱います。
- AuthName <realm>
- この認証の Realm を文字列で指定します。詳細は後述します。
- AuthUserFile <file>
- htpasswd コマンドで作成したパスワードファイルのフルパスを file に指定します。
- AuthGroupFile <file>
- ユーザーのグループを記述したファイルを file に指定します。グループの詳細は後述します。
- Require <user1> [<user2>...] | group <group1> [<group2>...] | valid_user
- アクセスを許可するユーザーを指定します。ここで指定されていないユーザーは、たとえ正しいパスワードを入力しても拒否されます。ユーザー名を空白区切りで指定すれば、それらのユーザーのみが許可されます。 "group" のキーワードの後にグループ名を空白区切りで指定すれば、それらのグループに所属するユーザーのみが許可されます。 "valid_user" とだけ指定すると、パスワードファイルにあるすべてのユーザーが許可されます。
これらは、前述の例のように各ディレクトリの ".htaccess" に記述することもできますし(ただし、該当ディレクトリの "AllowOverride AuthConfig" が有効になっている必要があります)、 Apache の設定ファイルの Directory ディレクティブ内に記述することも可能です。
htpasswd コマンドの詳細
AuthUserFile ディレクティブに指定するパスワードファイルの管理には、 htpasswd というコマンドを利用します。前述のとおり、ディストリビューションによってはコマンド名が微妙に違うこともあるので注意してください。以下、 htpasswd コマンドの主な使用方法をご紹介します。
パスワードファイルを新規作成する
パスワードファイルを新規作成して同時にユーザーを追加するには、以下のコマンドを実行します。
htpasswd -mc <ファイル名> <ユーザー名>
実行後、ユーザーのパスワードを 2 回尋ねてくるので、適切に入力してください。ファイル名で指定したファイルを作成し、そこにユーザー名で指定したユーザーのエントリーが追加されます。このコマンドを実行すると、たとえファイル名で指定したファイルが存在しても、それを削除して新規作成しますので注意してください。
ユーザーを追加せずにパスワードファイルの作成だけを行いたいなら、単純に touch コマンドなどで空のファイルを作れば OK です。その後、次のユーザーを追加する方法で必要なユーザーを登録することができます。
ユーザーを追加する
既存のパスワードファイルにユーザーを追加するには、以下のコマンドを実行します。
htpasswd -m <ファイル名> <ユーザー名>
パスワードファイルを新規作成するときと同様、ユーザーのパスワードを 2 回尋ねてきますので、適切に入力してください。ファイル名で指定したファイルにユーザー名のエントリーが追加されます。もしファイル名で指定したファイルが存在しない場合はエラーとなります。
パスワードを変更する
既存ユーザーのパスワードを変更する方法は、単純に同じユーザー名で追加するだけです。
htpasswd -m <ファイル名> <ユーザー名>
挙動もユーザーを追加するときとまったく同じです。当然、ユーザー名を間違うと新しいユーザーが登録されてしまうのでご注意ください。
ユーザーを削除する
ユーザーの削除は単純にパスワードファイル内の該当行を削除してもよいのですが、一応 htpasswd コマンドを使うこともできます。
htpasswd -D <ファイル名> <ユーザー名>
ファイル名に指定したファイルからユーザー名で指定したユーザーのエントリーを削除します。もし該当ユーザーのエントリーがなければエラーになります。
Realm について
単純にひとつのディレクトリ以下のアクセス制限を行うだけなら問題はないのですが、ときには違う場所にある別々のディレクトリに対して同じアクセス制限をかけたい場合があります。例えば、ドキュメントと画像ファイルを別々のディレクトリに保存していて、その両方に同じアクセス制限をかける場合などです。双方の AuthUserFile ディレクティブに同じファイルを指定すれば、アクセス制限自体は実現できますが、ユーザーはドキュメントにアクセスするときと画像にアクセスするときの 2 回、同じパスワードを入力しなくてはなりません。これではユーザーフレンドリーとは言えませんね。
こんなときは、双方の AuthName ディレクティブにも同じ文字列を指定しておくとよいです。 HTTP の規格で、同じホストから同じ Realm が送られてきた場合には、クライアントは以前の認証で使われたパスワードを自動的に送信することになっています。したがって、上記のような条件でもドキュメントにアクセスする際に認証を済ませてしまえば、画像のあるディレクトリでの認証は自動的に処理されます。
この仕組みの欠点として、共有サーバーでホスト名(FQDN)もシェアしている場合は注意が必要です。他のユーザーに自分と同じ Realm を指定されると、パスワードが漏れる恐れがあります。これを完全に防ぐ手段は、ホスト名を分けるか別の認証手段を使うしかありません。使用するのが自分だけなら、認証が必要なサイトにアクセスした後は必ずセッションを終わらせる(ブラウザーを終了させる)ように気をつけることで対処も可能ですが、なかなか確実に実行するのは難しいかもしれません。共有サーバーを利用している方はご注意ください。
グループの使用
前述のように、 Require ディレクティブを使うことでディレクトリごとにアクセスできるユーザーを制限することができます。この機能は、ユーザーをひとつのパスワードファイルで一元管理しながら、ディレクトリごとにアクセスできるユーザーを細かく調整することを可能にします。
しかし、サイトが大規模になってくると、各ディレクトリにアクセスできるユーザーのリストが分散してしまい、だんだんと見通しが悪くなってきます。漏れを防ぐためにも、各ディレクトリにアクセスできるユーザーリストも一元管理したいところです。こんなときは、 AuthGroupFile ディレクティブを利用するのが便利です。
AuthGroupFile ディレクティブに指定するファイルは、各行にグループ名とそれに所属するユーザーリストを並べたテキストファイルです。各行の書式は以下のようになります。
<グループ名>: <ユーザー名> [<ユーザー名>...]
例えば、 "neo", "smith", "morpheus" の 3 人のユーザーがいるとします。さらに "dir1", "dir2" という 2 つのディレクトリがあり、それぞれのアクセスを下表のように制限したいとしましょう。
ユーザー名 | dir1 へのアクセス | dir2 へのアクセス |
---|---|---|
noe | ○ | ○ |
smith | ○ | × |
morpheus | × | ○ |
この場合、グループファイルには以下のように記述します。もちろんグループ名は任意でかまいません。
group1: neo smith group2: neo morpheus
そして、 "dir1/.htaccess" は以下のように記述します。 "/path/to/passwd", "path/to/group" はそれぞれパスワードファイル、上記のグループファイルのフルパス名です。
AuthType Basic AuthName "Local host" AuthUserFile /path/to/passwd AuthGroupFile /path/to/group Require group group1
同様に、 "dir2/.htaccess" は以下のようになります。
AuthType Basic AuthName "Local host" AuthUserFile /path/to/passwd AuthGroupFile /path/to/group Require group group2
これで、前述の表に示したアクセス制限が実現できます。 Require ディレクティブには複数のグループを指定できますので、もし全員からアクセスしたいディレクトリがあれば、 "Require group group1 group2" などと記述すれば OK です。このようにすれば、グループファイルで各ディレクトリのアクセス制限を一元管理できるので、設定ミスなどを防ぐことができるでしょう。
以上で、 Apache での Basic 認証に関する事柄はだいたい網羅できているように思います。グループ機能などを駆使すれば、意外と大規模な用途にも使えそうですね。最近は認証機構に関してはWebアプリケーション側で実装することが多くなっていますが、その方法の欠点は、スクリプトを通さないとデータが保護できないことにあります。そのため、画像掲示板アプリなどの中には、画像の URL を直打ちすればユーザー認証なしでアクセスできてしまうものが多くあります。その点、 Basic 認証はサーバーレベルで制限されるため、すべてのリクエストが漏れなく認証されます。パスワードが平文で流れる問題は SSL を使えば解消できますし、 Basic 認証の利用がもう少し検討されてもいいような気がしますね。
詳しくはこちらの記事をどうぞ!
この記事にコメントする