NginxでBasic認証させる件

# ユーザーファイルを作成する
ユーザーファイルとはユーザー名と暗号化されたパスワード[^1]群。
Apacheで言うところの`.htpasswd`にあたります。

```text
# comment
ユーザー名1:暗号化されたパスワード1
ユーザー名2:暗号化されたパスワード2:comment
ユーザー名3:暗号化されたパスワード3
```

フォーマットもこの通りほぼ同じ。

パスワードの暗号化ですが、この節では`openssl`がインストールされている事を前提にして手順を記載してます。
Apacheの`htpasswd`を使ってもかまいませんが、わざわざそれをインストールする手間が省けます。

```bash
sudo sh -c "echo -n 'ユーザー名:$(openssl passwd -apr1 パスワード)' > '/usr/share/nginx/html/.htpasswd'"
# sudo不要&追記するなら
echo "ユーザー名:$(openssl passwd -apr1 パスワード)" >> "/usr/share/nginx/html/.htpasswd"
```

これで`/path/to/htpasswd/hoge`が作成されました。もちろんファイルパスはダミーですので適当に変えて使いましょう。

後はユーザーファイルの所有者やパーミッション[^2]を適切に設定しておくとよいです。
`nginx.conf`或いは任意の設定ファイルに記載されてる`user <ユーザー> [グループ];`と同じ所有者にする必要があります[^3]。

```bash
sudo chown ユーザー:グループ /path/to/htpasswd/hoge && sudo chmod 400 /path/to/htpasswd/hoge
```

所有者やパーミッションが合っていないとステータス`500`を返してきます[^2]。

あまりよろしくは無いですがパブリックディレクトリにユーザーファイルを置く場合はアクセスを排除するようにもしておきましょう。通常パブリックディレクトリにこのファイルを設置する必要はありません。

```nginx:nginx.conf
http {
	server {
		location ~ /\.ht {
			deny all;
		}
	}
}
```

# 設定する
`nginx.conf`か、あるいは`include`先でも。

```nginx:nginx.conf
# (省略)
http {
	#auth_basic           "closed site";
	#auth_basic_user_file /path/to/htpasswd/hoge;
	server {
		auth_basic           "closed site";
		auth_basic_user_file /path/to/htpasswd/hoge;
		location /himitsu/ {
			#auth_basic           "closed site";
			#auth_basic_user_file /path/to/htpasswd/hoge;
			limit_except GET {
				#auth_basic           "closed site";
				#auth_basic_user_file /path/to/htpasswd/hoge;
			}
		}
	}
}
```

auth_basicとauth_basic_user_fileが指定できるコンテキストは共にhttp, server, location, limit_exceptなので以上のような設定例で動きます。

個別のディレクトリにBasic認証をかけるにはどのコンテキストを使うかというとlocationになります。以上の例だと http://<ドメイン or IP>/himitsu/ にBasic認証がかかってますね。ディレクトリに限った話ではありませんが通常はこれを使用するのが無難かもしれません。

全体にBasic認証をかけるにはhttpかserverですが、httpはトップクラスのネストになるので**サーバー全体にBasic認証がかかる**ことに留意してください。
serverも似たような感じなのですがバーチャルホストを扱う場合は個別ドメイン毎に指定出来たりします。バーチャルホストを扱わないのであればどっちで指定しても同じかと思いますがそういうことが出来ると言うことを頭の隅っこの方にでも覚えておいてもらえれば変な事故を防げるときが来るかもしれません。
全体という意味でならlocationでも指定方法によっては全体にBasic認証をかけることもできます。

# 最後に

```bash
sudo service nginx reload
```

でBasic認証がかかっているか確認して下さい。`restart`でも反映できます。
`reload`の場合はサーバーを止めずに設定を反映できます。

# Apache VS Nginx
Apacheユーザーのための早見表。
Nginxは最後にセミコロンが要ることに注意！

| |Apache|Nginx|
|:-:|:-:|:-:|
|ユーザー認証の種類|`AuthType Basic`|N/A|
|認証領域の説明(名前)|`AuthName "hoge"`|`auth_basic "hoge";`<br><small>(auth_basic off;で認証無効化)</small>|
|ユーザー一覧のファイル指定|`AuthUserFile /path/to/htpasswd`|`auth_basic_user_file /path/to/htpasswd;`|
|グループ一覧のファイル指定|`AuthGroupFile /dev/null`|N/A|
|どのユーザーをリソースにアクセスさせるか|`Require valid-user`|N/A|
|コンテキスト|`ディレクトリ` `.htaccess`|`http` `server` `location` `limit_except`|

# パスワードの値には…(ネタ)
Nginx 1.0.3以上から[RFC 2307](http://tools.ietf.org/html/rfc2307#section-5.3)に記載されてるようにパスワードの値に

```text
ユーザー名:{スキーム}値
```

と指定できます。
これはApacheも同様。ただしどちらもバージョンによって使える、使えないスキームがあるので注意。

## Nginxで使えるスキーム
* `PLAIN`
* `SHA`(1.3.13から)
* `SSHA`

### PLAINってまさか…!!（ポロリもあるよ）
生のパスワードがそのまま使える…ヤバめ

```text
hoge:{PLAIN}012345678
```

絶対に使いたくないスキーム第一位に選ばれそうです。

## ApacheとNginxは推奨してない
`PLAIN`, `SHA`, `CRYPT`は安全ではないということで使用は避けた方が良いです。
結局上記で紹介している方法が無難ですね。
以上ネタでした。

# 参考文献
* [Nginx モジュール ngx_http_auth_basic_module](http://nginx.org/en/docs/http/ngx_http_auth_basic_module.html)
* [Apache パスワードフォーマット](https://httpd.apache.org/docs/2.4/misc/password_encryptions.html)

[^1]: 厳密には『ハッシュ値』です。理解しやすく「暗号化されたパスワード」などと表記してます。
[^2]: セキュリティー的な意味で「所有者」はユーザーに限定されので、パーミッションは`400`としてます。必要に応じて`400`以上に変えて下さい。
[^3]: 無い場合は`nobody`となります。 http://nginx.org/en/docs/ngx_core_module.html#user