それマグで!

知識はカップより、マグでゆっくり頂きます。 takuya_1stのブログ

習慣に早くから配慮した者は、 おそらく人生の実りも大きい。

Basic認証でHTTPSを必須にするために、HTTP→HTTPSへ誘導したい(したかった)

一杯書いてるけど、シンプルにいえば、

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でヤレよという話はいわない。

/auth_ldap/.htaccess
ErrorDocument 403 /403.php
/403.php
<?php

if( $_SERVER["SERVER_PORT"] != "443" ){
        header("Location: https://{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}");
        exit;
}

雑感

コレ考えるだけで3日ほど使った。しんどい。

AuthorizationやAuthenticationを承認とか認可・許可とか訳語がマチマチで困りますね。
用語として使うなら「身分の自己申告→身分照会→本人確認」が一番良いと思うんですね。証明書を持っていれば「呈示」でも良いんですが。本人が入力するだけなので、自己申告がいいですね。