どんな状況での話か
- 公開前や移行時の確認用のサーバーに、念のためパスワードを設定しておきたい
- 厳密なアクセス制限は必要なく、「URLにアクセスしただけでは見られない」という程度の制限でよい
- ウェブサーバーはnginxで、バックエンドのサーバーにプロキシしている
- バックエンドのサーバーで、BASIC認証やDigest認証が使われている
- つまり、nginxで単純にBASIC認証をかけてしまうと不都合がある
という稀によくありそうな状況で、既存の設定に影響をあたえること無く11行くらいで設定する方法についての話です。
注意事項
ユーザーが思った通りに認証情報を破棄できなかったりするので、本番運用でのアクセス制限として利用するものではありません。
設定前のファイル
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
server { | |
listen 80; | |
server_name default_server; | |
location / { | |
proxy_pass http://backend; | |
} | |
} |
な感じです。
設定後のファイル
11行(変数定義などで+4行)追加して以下のようになります。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
server { | |
listen 80; | |
server_name default_server; | |
set $secret_token 'ohkoNgi4quaoxahl'; # `$ pwgen 16 1` | |
set $base64 'dGVzdDp0ZXN0'; # `$ echo -n 'test:test' | base64` | |
location = /.secret-token-required.html { | |
if ($http_authorization = "Basic $base64") { | |
add_header Set-Cookie "secret_token=$secret_token;Path=/;Max-Age=31536000"; | |
return 302 /; | |
} | |
auth_basic "test site"; | |
auth_basic_user_file /dev/null; | |
} | |
if ($cookie_secret_token != $secret_token) { | |
rewrite ^ /.secret-token-required.html break; | |
} | |
location / { | |
proxy_pass http://backend; | |
} | |
} |
流れとしては、
- サーバーでは、秘密のcookieが確認できない場合にはBASIC認証が必要とのレスポンスを返す
- ブラウザでは、BASIC認証が設定されているときのダイアログが表示される
- サーバーでは、正しいパスワードが送られてきた場合には秘密のcookieを設定する
- それ以降は、秘密のcookieが設定されていればBASIC認証の情報は必要なくアクセスできるようになる
となっています。
あえてBASIC認証のダイアログである必要はなく、セキュリティ的には期待される動作と異なるUIで好ましくはないのですが、403的なページを用意するよりもパスワードのダイアログを出してしまった方が楽だし説明も省けるので、一時的な制限ならこんなのもありではないかと思います。
コメント