概要
Apache HTTP Server 2.4.13 で CGIPassAuth
ディレクティブ (公式マニュアル) がコア機能に追加されました。このディレクティブのデフォルト値は Off
です。On
をセットすると CGI (FactCGI) で Authorization
ヘッダーを環境変数で扱うことができるようになります。CGIPassAuth
ディレクティブは .htaccess でも使うことができるので、共用のホスティングサービスでも利用できることを意味します。
以前のバージョンでは mod_rewrite の RewriteRule
ディレクティブを使うかコンパイル時に SECURITY_HOLE_PASS_AUTHORIZATION
フラグを指定する必要がありました。これらの方法と比べて CGIPassAuth
ディレクティブのほうがかんたんです。
mod_cgi
、mod_cgid
、mod_proxy_fcgi
、mod_proxy_scgi
といった ap_add_common_vars()
を使うモジュールであれば CGIPassAuth
ディレクティブを考慮します。mod_include
と mod_ext_filter
といったリクエストを扱わないモジュールにも影響します。
Authorization
ヘッダーがデフォルトで扱えない理由
コンパイルオプションの SECURITY_HOLE_PASS_AUTHORIZATION
フラグに関連するコードを読むと Authorization
ヘッダーをデフォルトで読み込めないようにしているのは ps -e
で盗み見ることができることが挙げられています。
# https://github.com/apache/httpd/blob/ea64e031b97533efc10b5f73c8902fe72de9bd7e/server/util_script.c#L197.L209
/*
* You really don't want to disable this check, since it leaves you
* wide open to CGIs stealing passwords and people viewing them
* in the environment with "ps -e". But, if you must...
*/
#ifndef SECURITY_HOLE_PASS_AUTHORIZATION
else if (!ap_cstr_casecmp(hdrs[i].key, "Authorization")
|| !ap_cstr_casecmp(hdrs[i].key, "Proxy-Authorization")) {
if (conf->cgi_pass_auth == AP_CGI_PASS_AUTH_ON) {
add_unless_null(e, http2env(r, hdrs[i].key), hdrs[i].val);
}
}
#endif
mod_rewrite による対応方法
比較のために mod_rewrite の RewriteRule
ディレクティブを使う方法を示します。
# http://symfony.com/doc/current/setup/web_server_configuration.html
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
検証
Docker の公式イメージによる環境構築
コマンドツールの docker
および docker-compose
が導入されていることを前提とします。OS は Alpine Linux としました。PHP や HTML ファイルは www フォルダに設置します。Docker のほかの設定ファイルの例はこちらをご参照ください。
app:
image: alpine:3.4
volumes:
- ./www:/usr/local/apache2/htdocs
command: /bin/true
php:
image: php:7.1-fpm-alpine
ports:
- '9000:9000'
volumes_from:
- app
apache:
build: ./
ports:
- '80:80'
volumes_from:
- app
links:
- php
FROM httpd:2.4-alpine
RUN { \
echo 'LoadModule proxy_module modules/mod_proxy.so'; \
echo 'LoadModule proxy_fcgi_module modules/mod_proxy_fcgi.so'; \
echo ''; \
echo 'DirectoryIndex index.php index.html'; \
echo '<FilesMatch \.php$>'; \
echo ' CGIPassAuth On'; \
echo ' SetHandler "proxy:fcgi://php:9000"'; \
echo '</FilesMatch>'; \
} >> /usr/local/apache2/conf/httpd.conf
SetHandler
と ProxyPassMatch
Dockerfile に記載されている SetHandler "proxy:fcgi://php:9000"
の php
は docker-compose.yml
で指定した名前です。Docker を使っていなければ localhost
や 127.0.0.1
に書き換えることができます。SetHandler
による php-fpm の設定方法は Apache 2.4.10 から利用できます。
以前から使われていた ProxyPass
もしくは ProxyPassMatch
の場合、PATH_INFO
環境変数がセットされないために、SCRIPT_NAME
が正しく決定されない問題があります (PHP のバグレポート)。くわしくは mod_proxy_fcgi のマニュアルの環境変数の項目をご参照ください。
サービスの起動と停止
docker-compose.yml
、Dockerfile
、www/index.php
を設置したフォルダのなかで次のコマンドを実行すればサービスが起動します。
docker-compose up --build -d
サービスを停止させるには次のコマンドを実行します。
docker-compose stop
HTTP クライアントで確かめる
コマンドツールの curl
で確かめてみましょう。
curl -H 'Accept-Charset: utf-8' -H 'Authorization: hello' http://localhost:3000
サーバー側のスクリプト は次のようになります。HTTP_AUTHORIZATION
が存在することを確認します。
<?php
var_dump('hello' === $_SERVER['HTTP_AUTHORIZATION']);