読者です 読者をやめる 読者になる 読者になる

サブディレクトリで異なるユーザでBasic認証、Digest認証をかける

メモ。

典型的なBasic認証におけるHTTPクライアントとHTTPサーバの間の通信を紹介する。 だいたいの流れは以下のようになる。

  1. クライアントは認証が必要なページをリクエストする。しかし、通常ここではユーザ名とパスワードを送っていない。なぜならばクライアントはそのページが認証を必要とするか否かを知らないためである。
  2. サーバは401レスポンスコードを返し、認証領域 (authentication realm) や認証方式 (Basic認証) に関する情報をクライアントに知らせる。
  3. それを受けたクライアントは、認証領域(通常は、アクセスしているコンピュータやシステムの簡単な説明)をユーザに提示して、ユーザ名とパスワードの入力を求める。ユーザはここでキャンセルすることもできる。
  4. ユーザによりユーザ名とパスワードが入力されると、クライアントはリクエストに認証ヘッダを追加して再度送信する。
  5. 認証に成功すると、サーバは認証の必要なページのリクエストを処理する。一方、ユーザ名やパスワードが間違っていた時には、サーバは再び401レスポンスコードを返す。それによりクライアントは再びユーザにユーザ名とパスワードの入力を求める。

ja.wikipedia: Basic認証より)

一度、認証に成功したあとに他の認証が必要なページに移ってもパスワードの再入力を求められないのは、ブラウザが401レスポンスコードを得る度に先ほど入力された認証情報を返しているから。

実は私達は、ログアウト機能のない認証方式を知っています。それはHTTP認証(BASIC認証やダイジェスト認証の総称)です。HTTP認証の場合、サーバー側で認証状態は保持せずにリクエスト毎に認証するので、そもそもログアウトという概念がない(認証状態を保存しないので破棄の必要がない)のですが、利用者が入力したIDとパスワードをブラウザが一時的に保存するため、外見上は「ログイン状態が保持されている」ように見えます。
HTTP認証はログアウトができないので不便だという意見はよく目にしますし、それを克服するため、401応答ヘッダを返すことでHTTP認証のログアウトを実現するという例も見かけます。しかし、一般的には、HTTP認証はログアウトができない(ブラウザがIDとパスワードを保持したままになる)ので、以下のような「運用で対処」している場合が多いでしょう。

  • ブラウザを終了する(HTTP認証のID・パスワードは消える)
  • ブラウザの機能によりHTTP認証のID・パスワードを消去する

徳丸浩の日記:ログアウト機能の目的と実現方法 より)

このため、上位ディレクトリで入力した認証情報が下位ディレクトリにも引き継がれてしまう。

http://hogehoge.jp/targetdirBasic認証やDigest認証でアクセス制御し、http://hogehoge.jp/targetdir/admin は管理者だけがアクセスできるようにするためにはどうするか。Do You PHP はてな: 特定のサブディレクトリに別のBASIC認証をかけるによると、DirecotryディレクティブとLocationディレクティブの読み込み順番と上書き設定を利用して実現できるとのこと。

Apache 2.2系だと、.htaccess でDirectoryディレクティブとLocationディレクティブの設定は許されていないので、httpd.conf に直接書く。
DebianUbuntu系ならば /etc/apache2/sites-avaiable/ 以下の設定ファイルに、RedHatCentOS系ならば /etc/httpd/conf.d 以下の設定ファイルに以下を書き加える。以下はDigest認証の例。Apache 2.0系と2.2系では設定が違うので注意。2.4系にはまだ追いつけていないのでわからない。

<Directory "/path/to/targetdir">
  〜 省略 〜

     AuthType Digest
     AuthName "Users"

     # Apache 2.0
     #AuthDigestFile "/other/path/to/.htpasswd"

     # Apahce 2.2 later
     AuthDigestProvider file
     AuthUserFile "/other/path/to/.htpasswd"
     AuthGroupFile /dev/null
     Require valid-user

     Satisfy All
</Directory>

<Location "/targetdir/admin"> 
     AuthType Digest
     AuthName "Admins"

     # Apache 2.0
     #AuthDigestFile "/another/path/to/.htpasswd"

     # Apahce 2.2 later
     AuthDigestProvider file
     AuthUserFile "/another/path/to/.htpasswd"
     AuthGroupFile /dev/null
     Require valid-user

    Satisfy All
 </Location>

targetdirへのアクセス用ユーザアカウント作成

% htdigest -c /other/path/to/.htpasswd "Users" hoge (パスワードファイル作成時)
% htdigest /other/path/to/.htpasswd "Users" hoge (パスワードファイル存在時)

targetdirへのアクセス用ユーザアカウント作成

% htdigest -c /another/path/to/.htpasswd "Admins" admin (パスワードファイル作成時)
% htdigest /another/path/to/.htpasswd "Admins" admin (パスワードファイル存在時)

リンク