Apacheのアクセス制御、mod_rewrite設定 (httpd.conf, .htaccess)

# 一般のアクセス制御設定 

## Order (Allow, Deny)
アクセス権限のマッチングの順番を決める。

```apache
Order deny,allow
```
は、Denyが先行なので、Deny条件にマッチしたら、Allow条件を調べる。

逆に

```apache
Order allow,deny
```
は、Allowが先行なので、Allow条件にマッチしたら、Deny条件を調べる。

条件は

```apache
Allow from 192.168.0.1 192.168.1.0/24
Deny from 192.168.30.1
```
のように記述する。
条件を記述しなかった場合、必ずパターンマッチングで失敗する。


分かりづらいのだが、
**条件にマッチしない場合はそこでマッチングが打ち切られて
マッチングの対象(Allow, Deny)と反対のアクセス処理が行われる。**


例えば最初の
Order deny,allow の場合

- Deny条件にマッチしないなら、この時点で(Allow条件を見ずに)アクセスを**許可**する
- Deny条件にマッチしたら、さらに Allow条件を調べて
- -->Allow条件にマッチしないなら、アクセスを**拒否**する
- -->Allow条件にマッチしたら、アクセスを**許可**する

↓はほとんどのユーザは通さないけど、一部の信頼できるユーザのみを通したい場合によく使う。

```apache
Order deny,allow
Allow from 192.168.1.0/24
Deny from All
```


Order allow,deny の場合も同様に

- Allow条件にマッチしないなら、この時点で(Deny条件を見ずに)アクセスを**拒否**する
- Allow条件にマッチしたら、さらに Deny条件を調べて
- -->Deny条件にマッチしないなら、アクセスを**許可**する
- -->Deny条件にマッチしたら、アクセスを**拒否**する

↓はほとんどのユーザは通すけど、一部のやばいやつを拒否したい場合によく使う。

```apache
Order allow, deny
Allow from All
Deny from 192.168.0.1 192.168.0.3
```


### 設定のポイント

必ず、AllowかDenyのどちらか一方をAllで指定すること。

Allow、DenyともにALL指定がない場合、
記述上、AllowでもDenyでもないアドレスが存在してしまう。
それでも処理はパターンマッチングの順に従って行われるが、きちんと可読性を保つことが大事。

例えば、全ユーザにアクセスを許す場合

```apache
Order deny,allow
```
の記述のみで全ユーザにアクセスが許される(Deny条件がないので、必ずパターンマッチングに失敗する)が、
Orderの順で、Denyが先行してしまっているのでパット見分かりづらい。

明示的に全ユーザにアクセスを許すように

```apache
Order allow, deny
Allow from All
```

とした方が私は百倍読みやすい。

## AuthType

アクセス制御方法には、IPアドレスを使ってAllowやDenyを設定する方法以外に
ユーザ名とパスワードでアクセスを許可する方法がある。


- AuthType：BASIC認証を使う場合は"Basic"、Digest認証を使う場合は"Digest"
- AuthName：ダイアログ上に表示される説明用の文字列
- AuthUserFile：パスワードファイルへのパス
- Require：パスワードファイルに存在する全ての認証されたユーザに、ディレクトリへのアクセスを許可する場合は"valid-user"、パスワードファイル中の一部のユーザにのみアクセスを許可する場合は、ユーザ名をスペース区切りで"user username [username] ..."のように指定する。

BASIC認証の場合、パスワードがそのままの形で通信されてしまうので盗聴などの被害を受ける可能性がある。
Digest認証の場合、パスワードが暗号化されて通信されるのでセキュリティ被害に強くなるが、昔のブラウザ(IE6以前)では対応していない。
が、普通に最近のブラウザを利用していればDigest認証が使えるはずなので、Digest認証を使うべきだろう。

```apache
<Directory "/etc/apache/htdocs/secret_space">
  AuthType Digest
  AuthName "Input username and password!"
  AuthUserFile "/etc/hoge/.passwd"
  Require valid-user
</Directory>
```

## Satisfy
IPアドレス認証と、ユーザ認証によるアクセス制御は共に組み合わせることができる。

IPアドレス認証とユーザ認証を同時に満たさないとアクセスできないよう指定する場合はAll（デフォルト）を指定する。

```apache
Satisfy All
```

どちらかの認証条件を満たせばアクセスできるようにする場合はAnyを指定する。

```apache
Satisfy Any
```

Anyを使ったとき、ディレクトリへのアクセス制御指定の全体はこんな感じになる。

```apache
<Directory "/etc/apache/htdocs/secret_space">
  Order Deny,Allow
  Allow from 192.168.0.1/24
  Deny from All
  AuthType Digest
  AuthName "Input username and password!"
  AuthUserFile "/etc/hoge/.passwd"
  Require valid-user
  Satisfy Any
</Directory>
```

## AllowOverride 

All|None|directive-type [directive-type] ...のいずれかで
.htaccessで許可するdirectiveを記述する。
directive-typeにはAuthConfig,Limit,Optionsなどがある。

何も指定がない場合はデフォルトでAllが設定される。

Allにすると各ディレクトリ内に含まれる.htaccessのdirectiveが全て有効になる。

```apache
AllowOverride All
```

Noneにすると各ディレクトリ内に含まれる.htaccessのdirectiveが全て無効になる。

```apache
AllowOverride None
```

## Options

Options は、特定のディレクトリに対して どの機能(オプション)が使用可能かを制御する。

### Optionの例

- All(デフォルト) ... MultiViews を除いた全ての機能が有効となる。
- ExecCGI ... CGI スクリプトの実行を許可。
- Indexes ... もし、URL がディレクトリにマップするリクエストであって、 且つ DirectoryIndex で指定したファイル (例えば、index.html) が ディレクトリ内に無ければ、mod_autoindex が ディレクトリ内の一覧を整形して返す。
- MultiViews ... コンテントネゴシエーションを有効にする。
- FollowSymLinks ... サーバが、このディレクトリ内でシンボリックリンクをたどれるようにする。mod_rewriteを使う時に必要。


``` apache
Options All
```

# mod_rewrite設定

## RewriteEngine

mod_rewriteを利用するならON;利用しないならOFF;

``` apache
RewriteEngine On
# RewriteEngineをONにするためには、OptionsでFollowSymLinksを有効にする必要がある。
```

## RewriteRule

URLを書き換える際のルールを設定する。
記述の形式は以下のようになっている。

```apache
RewriteRule Pattern Substitution [flags]
```

Pattern, Substitutionは正規表現で記述できる。
URLがPatternに一致する場合、新しいURLがSubstitutionに置き換えられflagsがあるならばそのflagsに従った動作を行う。

### flagの例

- L|last ... mod_rewriteによるURL書き換えのマッチング処理を終了する。（終了しない場合は置換されたURLが、この後に続くRewriteRuleにて再度パターンマッチングが行われる。）
- R|redirect ... リダイレクトでの通常のHTTPレスポンス"302 Moved Temporaily"を返す。

例えば、

```apache
<Directory />
  RewriteEngine On
  RewriteRule ^old/test\.html$ new/test.html [R]
</Directory>
```

の場合、/old/test.htmlへのアクセスがあると、302をブラウザに返して/new/test.htmlへリダイレクトする。

## RewriteBase

RewriteBaseは書き換え後のパス指定が相対パスだった時にURLのprefixとして使われる。
例えば

```apache
<Directory />
  RewriteEngine On
  RewriteBase /after
  RewriteRule ^hoge\.html$ hage.html [L]
</Directory>
```

なら、/hoge.htmlへのアクセスは、/after/hage.htmlへリダイレクトされる。




## RewriteCond 

RewriteCondでRewriteRuleを行うのに必要な条件を記述することができる。
RewriteCondが複数指定された場合は、全ての条件に一致した場合にのみ続くRewriteRuleが適用される。
RewriteCondによる条件判定ではもちろんURLも使用できるが、ユーザーエージェント、日付、曜日も条件として使用できる。


### RewriteCondで使える変数の例

- HTTP_USER_AGENT
- HTTP_REFERER
- REQUEST_URI
- TIME_YEAR
- TIME_MON
- TIME_DAY
- TIME_HOUR
- TIME_MIN
- TIME_SEC
- TIME_WDAY
- TIME

変数を使う時は、%{}の{}の中に変数名を記述すること。

例）

```apache
# 来年のエイプリルフール特設ページの仕込み
RewriteEngine on
RewriteCond %{TIME_YEAR}%{TIME_MON}%{TIME_DAY} "=20150401"
#サイトへの全てのアクセスをfool.phpへリダイレクトする
RewriteRule ^/.*$ http://www.example.com/fool.php [R]
```

# 参考資料

core - Apache HTTP サーバ バージョン 2.2
http://httpd.apache.org/docs/2.2/ja/mod/core.html

Apacheのアクセス制御をちゃんと理解する。 - こせきの技術日記
http://koseki.hatenablog.com/entry/20100913/ApacheAccessControl

mod_rewrite よく使う条件 - Qiita
http://qiita.com/asahina_dev/items/0848a1b557b7a458f730