tl;dr
えのかわです。Nginx で特定パスのみ Basic 認証を有効化したい場面に遭遇したので備忘録として残します。前提として、Nginx の Backend には php-fpm が存在するものとします。
なぜmapか
ngx_http_map_module を利用することで、シンプルに条件を記述することが可能です。パス毎に location を記載するのも一つの手段ですが、期待する挙動とならずに苦戦してしまい map モジュールを使うことにしました。(おい
nginx.confにmapを定義
まずは /etc/nginx/nginx.conf に map を定義します。今回は /sample/ もしくは /admin/ 配下にリクエストがあった際に Basic 認証を有効化させるものとします。
map $request_uri $auth {
default off;
~^/sample/.* "Basic Authentication";
~^/admin/.* "Basic Authentication";
}
~ は正規表現の利用を宣言しています。前述のドキュメントにも下記の様に正規表現の記載があります。
A regular expression should either start from the “~” symbol for a case-sensitive matching, or from the “~*” symbols (1.0.4) for case-insensitive matching. A regular expression can contain named and positional captures that can later be used in other directives along with the resulting variable.
ハマったのが、map を定義する conf です。/etc/nginx/conf.d/ 配下の default.conf に定義しようとすると、下記の様にエラーが発生しました。
2019/11/25 15:01:35 [emerg] 1#1: "map" directive is not allowed here in /etc/nginx/conf.d/default.conf:8 nginx: [emerg] "map" directive is not allowed here in /etc/nginx/conf.d/default.conf:8
こちらも前述のドキュメントに丁寧に Directives が記載されていますね。nginx.conf というよりは、http Directive に記載しましょう。が正しいですね。ちゃんとドキュメントを読みましょう。はい。(スミマセン
Syntax: map string $variable { ... }
Default: —
Context: http
default.confにauth_basicを定義
下記の様に Basic 認証の設定を記載します。
location ~ \.php$ {
root /var/www/html/public;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
+ auth_basic $auth;
+ auth_basic_user_file /etc/nginx/.htpasswd;
}
キモは auth_basic の値が $auth となっている点です。nginx.conf で定義した map の値を参照して振る舞います。ngx_http_auth_basic_module の仕様上、auth_basic の値が off の場合は Basic 認証をキャンセルします。先ほど定義した map には default off; と記載されているため、/sample/ もしくは /admin/ 配下へのリクエストがあった場合にのみ Basic 認証が有効化され、それ以外のパスへリクエストがあった場合は Basic 認証をキャンセル(off)します。
Enables validation of user name and password using the “HTTP Basic Authentication” protocol. The specified parameter is used as a realm. Parameter value can contain variables (1.3.10, 1.2.7). The special value off allows cancelling the effect of the auth_basic directive inherited from the previous configuration level.
余談
location Context で if を利用することが可能ですが、Nginx としては推奨していないようです。Nginx 公式が If Is Evil (if Directive は悪)と謳っていることから、信憑性は高いでしょう。Qiita やその他ブログを漁ったところ、map ではなく if で判定している内容もちらほら見られたので、気をつけようと思いました。
まとめ
ちゃんと公式ドキュメントは読みましょう。(戒め