「htaccessで特定環境の時だけBASIC認証をかけたい」
「htaccessで複雑なリクエストURIの時だけBASIC認証をかけたい」
こんにちは、タカフです。
.htaccess便利ですよね。
Webアプリケーションを色々カスタマイズするときに欠かせない.htaccessですが、いかんせん記述ルールが覚えづらい!!
その独特な記述ルールから、覚えても実装する時は不安だったりするので結局毎回ググってはいる気がします。
そんな中、Apache2.4になってより細かい制御も出来るようになり、ちょっと目から鱗のコードがあったので紹介します。
環境毎にBASIC認証をかける
Apache2.4からはIfディレクティブが使えるようになり、より細かい制御が出来るようになりました。
例えば開発環境の時だけBASIC認証をかけたい時などは次のように記述します。
<If "%{HTTP_HOST} == 'dev.example.com'">
AuthUserFile /path/to/your/.htpasswd
AuthGroupFile /dev/null
AuthName "Basic Auth"
AuthType Basic
Require valid-user
</If>
直感的でわかりやすいですよね。これはよくある使い方です。
特定リクエストURIの時だけBASIC認証をかける
これが目から鱗の内容でした。
上述のようにHOST名で処理制御するくらいだったらわりと簡単でしたが、
リクエストURIによってBASIC認証をかけたい時もありますね。
例えば、 /admin/xxxxx
みたいな管理系URIだけBASIC認証をかけたい時です。
こういう場合、admin以下を全て対応する為に正規表現でそのURIを記述したりしますが、
この時、.htaccessでの正規表現パターン自体をスラッシュで囲うのでスラッシュそのものを書くときに困ったものなのです。
なので、一般的にはエスケープはバックスラッシュでエスケープするので以下のように記述するのですが、
<If "%{REQUEST_URI} =~ /\/admin\/.*/">
これはNGです。
忌まわしき 500 : Internal Server Error
が出てきます。
これをどうするかというと以下のように記述します。
<If "%{REQUEST_URI} =~ /\x2Fadmin\x2F.*/">
なんとスラッシュを \x2F
で表すのです。
これは知らなかったですね。目から鱗が落ちた音がしました。
これは信頼と実績のstackoverflowで発見しました。
https://stackoverflow.com/questions/15142532/how-can-i-escape-slash-sign-in-apache-if-directives-regex
こういう情報は海外サイトの方が圧倒的に見つかりますね。
おまけ:条件を組み合わせてBASIC認証をかける
Ifディレティブは条件を組み合わせても使うことが出来ます。
ですので、
開発環境では全部BASIC認証をかけて、
本番環境では管理系URIだけBASIC認証をかける、
というような条件も可能です。
例えば、以下のような記述になります。
<If "%{HTTP_HOST} == 'dev.example.com'">
AuthUserFile /path/to/your/.htpasswd
AuthGroupFile /dev/null
AuthName "Basic Auth"
AuthType Basic
Require valid-user
</If>
<If "%{HTTP_HOST} == 'www.example.com' && %{REQUEST_URI} =~ /\x2Fadmin\x2F.*/" >
AuthUserFile /path/to/your/.htpasswd
AuthGroupFile /dev/null
AuthName "Basic Auth"
AuthType Basic
Require valid-user
</If>
便利ですね。
まとめ
Apache2.2の頃は特定ディレクトリに.htaccessを設置すればそれ以下のディレクトリにBASIC認証をかけられましたが、
最近ではWordPressもPHPフレームワークもhtaccessでリクエストを集めてルーティング処理をしてディレクトリ自体が実在しないので、Apache2.2の書き方では通用しなくなっていました。
なのでこのような問題が発生するのでした。
以上、カフーブログの提供でお送りしました。