一杯書いてるけど、シンプルにいえば、
Authと転送は両立できない。転送を諦めて、SSLRequireSSLを.htacessに書くだけ。
Basic認証を見直してみる
Basic認証は手軽で便利です。Rediscover Basic認証。Basic認証を使うことで、LDAP連携が出来るしDBMや、MySQLをバックエンドに使えたり。ノウハウを確立しておくと意外と重宝する。
簡単に言えば
Apacheの認証= require valide-user を使う。
パスワードが経路で丸見えになるのであまり使われない。でも便利。
そこでHTTPSで使うことになる。Basic認証とHTTPSで、一応は安心で簡単な認証とアクセス制限を実現出来る。
Basci認証はHTTPの正式な認証手段
HTTPのヘッダにちゃんと定義されている
WWW-Autenticate
ヘッダがあるのでブラウザは必ず実装するので、必ず使える。
アクセス制御について
あるコンテンツにアクセス可能(GET)かどうかを次のように表現する
認証内容 | - |
---|---|
そのURIが存在する・しない | access |
誰がそのURIにアクセスしているのか、自己申告させ、照会する | identify+authenticate |
その人は、URIへの読込(GET)権限があるのか | access right + authorize |
これをHTTPのステータスコードと併せると次のようになると思う
認証内容 | コード |
---|---|
そのURLが存在しない | 404 |
本人が自己申告を嫌がった | 401 |
自己申告したが、本人照会出来なかった | 401 |
本人だったが、利用権限がなかった | 403 |
Apacheの認証
本人確認を要求する | require valid-user |
権限を確認する | limit GET POST |
IPで承認を切分る | Allow from XXX.XXX.XXX.* |
複数条件を組み合わせる。
条件は柔軟に書きたくなる。
- ユーザー+グループ
- ユーザー、またはIP
などと組み合わせて使いたくなる。
Satisfyが使える。
Satisfy All| Any
を使って複数条件をAND/OR でつないで使うことが出来る。
Satisfy | All | Any |
意味 | AND | OR |
でつなぐことが出来る。
Satisfyが適用される例
Satisfy Allの場合 | |||
条件1 | true | true | true |
条件2 | true | true | false |
条件3 | true | false | n/a |
結果 | 200 | 403 | 403 |
Satisfy anyの場合 | |||
条件1 | true | fasle | false |
条件2 | n/a | true | false |
条件2 | n/a | n/a | true |
結果 | 200 | 200 | 200 |
n/aと書いた箇所は到達前に認証失敗になる
まぁ当たり前なんだけど。。。
条件の適用順
.htaccess
directory
location
virtualhost
だったと思う。
設定に書いた条件は、Apacheがマージして順番に適用するので、認証にまつわる部分をmod_rewriteで書き換えても無駄骨になると思う。
そして、mod_rewriteのような必殺仕事人より先にディレクトリの存在がチェックされたりしてややこしいので無理はしない方がよかった。
mod_rewriteで書き換えられると思ってた。でも認証と組み合わせると実行順が存在チェック→アクセス権→Rewriteになってて面倒だった。
その他の認証条件(SSLを必須にする)
Basic認証はHTTPSと組み合わせて使うが。HTTPでアクセスしてもBasic認証のダイアログが出てきて困る。HTTPでアクセスしたら拒否して、HTTPSを必須にした方がいい。
HTTPでのアクセスを拒否するには
SSLRequireSSLを使う。
SSLRequireSSLを使うとどうなるか
SSLRequireSSL
Satisfy All (デフォルト)で使った場合
HTTPSアクセス | HTTPアクセス | |
SSLRequireSSLの結果 | true | false |
Basic認証の結果 | true | n/a |
結果 | 200 | 403 |
になる。
HTTPでアクセスしたら、403が表示されるだけという非道なサーバーができあがる。
HTTP→HTTPSへ誘導をすることが出来きないので、誘導してあげたい。
mod_rewriteで誘導する
無理。
403エラーページを利用する。
Authが無ければ、rewrite 転送でうまく行く
RewriteEngine On RewriteCond %{SERVER_PORT} !^443$ RewriteRule ^.*$ https://%{SERVER_NAME}%{REQUEST_URI}
たぶん、内部プロキシすればいいような気もしたが、無限ループになったら嫌なのでやめた。
Satisfy Any の場合。
あまりないと思うけど。Satify Anyになっていると、HTTPSでアクセスでOKになってしまう。
Satisfy Anyで使った場合
HTTPSアクセス | |
SSLRequireSSL | true |
Basic認証 | n/a |
結果 | 200 |
これは困るので、HTTPSはSatisfyから分離する。
<VirtualHost _default_:443> #(ry) SSLOptions +StrictRequire </VirtualHost>
結局 Basic認証手前でHTTPSへ転送できかなった。
mod_rewrite と mod_auth+core のsatisfy 実行順の関係でうまく行かないっぽい。
最大限出来ること
403エラーページへの転送を利用する
403エラーページへの転送は内部的に行なわれるので、これをPHPに設定し、PHP側から、HTTPSに飛ばす。
PHP使うなら、はじめからBasic認証もPHPでヤレよという話はいわない。
/403.php
<?php if( $_SERVER["SERVER_PORT"] != "443" ){ header("Location: https://{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}"); exit; }
雑感
コレ考えるだけで3日ほど使った。しんどい。
AuthorizationやAuthenticationを承認とか認可・許可とか訳語がマチマチで困りますね。
用語として使うなら「身分の自己申告→身分照会→本人確認」が一番良いと思うんですね。証明書を持っていれば「呈示」でも良いんですが。本人が入力するだけなので、自己申告がいいですね。