PHPのセッション関連設定項目

なんか[似たような設定項目がいっぱい](http://php.net/manual/ja/session.configuration.php)あってわかんねーよ！とよくなるので自分用メモ。
基本的にPHP_INI_ALLなので何処でも設定可能。


# 有効期限関連

## session.cookie_lifetime

ブラウザにセッションIDのCookieを発行する際のCookieの有効期限。
ブラウザはこの期限を過ぎるとCookieを破棄するので、結果としてセッションが途切れることになる。
デフォルトは0で"ブラウザを閉じるまで"という意味。

## session.gc_maxlifetime

サーバに保存されているセッションファイルを保護する有効期限。
セッションデータそのものの有効期限ではないし、そのような設定項目はない。
リロードされないまま有効期限を過ぎたら、その後セッションファイルが削除される可能性がある。
デフォルトは1440秒。

## session.gc_probability
## session.gc_divisor

session.gc_maxlifetimeを過ぎると必ずセッションファイルが削除されるわけではなく、PHPにリクエストがあったときに(session.gc_probability / session.gc_divisor)の確率でGCが起動して実際に削除される。
セッションファイルそのものには有効期限は書かれていないため、session.gc_maxlifetimeを過ぎてもGC起動前であればセッションデータにアクセス可能。
デフォルトはsession.gc_probability=1、session.gc_divisor=100で、1%の確率でGCが起動する。


# セッション生成関連

## session.sid_length

PHP7.1.0で導入された。
セッションIDの文字列長を指定する。
長ければ長いほど推測されにくい。
デフォルトは32で、256まで設定可能。

## session.sid_bits_per_character

PHP7.1.0で導入された。
セッションIDに使用する文字種を指定する。
デフォルトは4で`[0-9a-f]`の16進数文字列を使用する。
5で`[0-9a-v]`、6で`[0-9a-zA-Z_\-]`となるが、5が推奨されているようだ。

## session.lazy_write

セッションデータが変更されたときにのみセッションファイルを書き込む。
デフォルトは1で有効。
変更されなかった場合セッションファイルの有効期限はどうなるんだろう？

# サーバ側設定

## session.save_path

セッションファイルを保存するディレクトリを指定する。
デフォルトは`/tmp`等になっていて、基本的に変更しなくていい。
ただし、ひとつのサーバで`session.gc_maxlifetime`の異なる複数のシステムを運用する場合は分けなければならない。
分けないと`session.gc_maxlifetime`が短いほうのタイミングでセッションファイルが削除されてしまう。

## session.save_handler

セッションデータの保存・取得方法を[まるごと差し替える](http://qiita.com/rana_kualu/items/45afbb591eb8195d2518)。
セッションデータをデータベースに保存したい場合などに使う。

## session.use_strict_mode

サーバ側で発行していないセッションIDが送られてきた場合はそれを許可せず、サーバ側で新しいセッションIDを発行する。
デフォルトは0で、`PHPSESSID=hoge`とか適当なCookieを送りつけてもそのIDでセッションが有効になる。

あまり現実的とは言えないが、`session.use_trans_sid`等と複合することで[セッション固定攻撃](http://bakera.jp/glossary/%E3%82%BB%E3%83%83%E3%82%B7%E3%83%A7%E3%83%B3%E5%9B%BA%E5%AE%9A%E6%94%BB%E6%92%83)が可能になるので、とりあえず1にしておいても損はないだろう。

# ブラウザ側設定

## session.name

セッション名としてCookieに設定される。
デフォルトはPHPSESSID。
同一ドメインで無関係な別のシステムを運用する場合は分けた方がよい。
が、それ以前にサブドメイン切った方がいい。

## session.cookie_domain
## session.cookie_path
## session.cookie_secure
## session.cookie_httponly

Cookieの[Domain属性](https://triple-underscore.github.io/RFC6265-ja.html#section-4.1.2.3)、[Path属性](https://triple-underscore.github.io/RFC6265-ja.html#section-4.1.2.4)、[Secure属性](https://triple-underscore.github.io/RFC6265-ja.html#section-4.1.2.5)、[HttpOnly属性](https://triple-underscore.github.io/RFC6265-ja.html#section-4.1.2.6)をそれぞれ指定する。

`session.cookie_secure`はCookieをSSLの場合にのみ送信する設定で、trueにした方がよい。
ただしHTTPとSSLでセッションを継続させることができなくなる。

`session.cookie_httponly`はJavaScript等からCookieを読み込めなくする設定で、trueにした方がよい。
`session.cookie_secure`の反対の意味ではない。

`session.cookie_domain`は[指定しない方がよい](http://blog.tokumaru.org/2011/10/cookiedomain.html)。
`session.cookie_path`は[指定してもあまり意味がない](http://qiita.com/rana_kualu/items/ec1a965cec895a87699a)。


# ブラウザキャッシュ

## session.cache_limiter

ブラウザやプロキシサーバがWebページのキャッシュをどう扱うかを指定する。
セッションとはあまり関係ない。
設定可能な値は"public"、"private_no_expire"、"private"、"nocache"。

"public"はブラウザ、プロキシサーバ共にキャッシュを認める。
ブラウザバックでリクエストを送りなおさずブラウザのキャッシュを読み込む。
キャッシュの有効期限はsession.cache_expireで指定。

"private"はブラウザのキャッシュは許可、プロキシサーバには認めない。
"private_no_expire"は"private"と同じだが[Expires](https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/Expires)ヘッダを送信しない。
FirefoxがExpiresを理解できないことがあるからということらしいが、最近のブラウザであれば気にする必要は無いだろう。

デフォルトは"nocache"でブラウザもプロキシサーバも一切キャッシュしない。
ブラウザバックなどでも毎回リクエストを送りなおす。

## session.cache_expire

session.cache_limiterをpublicやprivate_no_expireにした場合にのみ意味を持つ。
ブラウザキャッシュの有効期限で、期限を過ぎるとブラウザキャッシュを破棄してサーバに読み込みに行くようになる。
デフォルトは180だが、session.cache_limiterを変更しない限り実質無意味。


# 変更禁止

## session.use_cookies
## session.use_only_cookies

セッションの保存にCookieを使用するか。
両方ともデフォルトは1で、0にしてはいけない。
`session.use_cookies`は「Cookieを使用してもいいか」、`session.use_only_cookies`は「必ずCookieを使用するか」。

`session.use_only_cookies=0`にすると、`index.php?PHPSSID=hoge`というURLでセッションIDが有効になり、容易にセッションハイジャックできてしまうため、0にしてはならない。

## session.use_trans_sid
## session.trans_sid_hosts
## url_rewriter.tags
## session.trans_sid_tags

aやformタグへのリンクに自動的にセッションIDを追加する。
そもそも`session.use_only_cookies`でCookie以外のセッション制御は無効になっているので出番はない。

## session.referer_check

リファラに特定の文字列がないとセッションを維持しないようにする。
デフォルトは空文字列でリファラチェックを行わない。
OAuthするだけで死ぬので運用に耐えない。

## session.auto_start

リクエスト時自動的にsession_start()される。
デフォルトは0で、変更すべきではない。

## session.serialize_handler

セッションデータのシリアル化方法の設定。
デフォルトは"php"で、[session_encode](http://php.net/manual/ja/function.session-encode.php)関数を使う。
余程の理由がないかぎり変える必要は無いだろう。



# 古い設定

## session.hash_function
## session.hash_bits_per_character
## session.entropy_file
## session.entropy_length

PHP7.1.0で削除された。
セッションIDの生成方法に関する設定だが直感的ではなかったため、わかりやすい[random_bytes()](http://php.net/manual/ja/function.random-bytes.php)を使う方法に[変更された](https://wiki.php.net/rfc/session-id-without-hashing)。


# まとめ

セッションの有効期限を変えるには、最低限ブラウザ用の`session.cookie_lifetime`とサーバ用の`session.gc_maxlifetime`を設定すればよい。