Spring-Session@1.3.0の検証

この記事を参考にしながらSpring-Sessionを試してみた
特に、アノテーションではなくXMLベースでの設定をやりたかった。

* [Spring-Sessionを使ってみた](http://qiita.com/uich/items/cd5d63c12f1d342fc65c)
* [Spring-Session@1.2.1の簡単な検証](http://qiita.com/uich/items/416101275ec00044765c)

# Spring-sessionのドキュメント

公式ドキュメントにXMLでの設定例が載っている。

* [Spring Session - HttpSession (Quick Start)](http://docs.spring.io/spring-session/docs/current/reference/html5/guides/httpsession-xml.html)

## 最終的なBeanの設定

* web.xmlの設定は必須なので、他の記事を参考にして設定してください
* Beanの設定は次のブログを参考にした [spring-session学习](http://blog.csdn.net/zcl111/article/details/51700925)
  * 中国語なので詳しくはわからないが、クッキーの生成されるタイミングも含めて詳しい解説がある

* 次のブログにある設定を試している [Spring-session & redis 子域名共享session](http://blog.csdn.net/beflyabot/article/details/51449315)

この設定を適用すると

* `cookieName`：　デフォルトのCookie名を上書きできる
* `domainNamePattern`： 正規表現で複数ドメインを１つのドメインとみなしてクッキーを発行できる
    * 例えば `a.example.com`, `b.example.com` は下の正規表現でキャプチャーすると `example.com`になる
    * 検証コード → [Wandbox
](http://melpon.org/wandbox/permlink/x0MWIMTRSuJxPQpE)
    * ということは、複数サーバ間でセッションを共有できる
    * 英語で調べるときは「session replicate」もしくは「session clustering」で検索するとよさそうだ。

* `domainName`: 正規表現を使わずにホスト名を直接指定する（domainNamePatternでうまく動かないときは、こちらを使ったほうがいいかもしれない）
  * `<property name="domainName" value=".example.com"/>`

```xml
    <!-- spring-session内のアノテーションを有効化する -->
    <context:annotation-config/>

    <!-- Spring-session側のセッション管理クラスを有効化 -->
    <bean class="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration"/>
    <!-- Redisのクライアント実装をbeanに登録 -->
    <bean class="org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory"/>

    <!-- デフォルトのクッキー設定を上書きする -->
    <bean class="org.springframework.session.web.http.DefaultCookieSerializer">
        <property name="cookieName" value="JSESSIONID" />

        <!-- ドメイン名を"."で始める -->
        <property name="domainName" value=".example.com"/>

        <!-- 正規表現はちょっと未確認 -->
        <!-- <property name="domainNamePattern" value="^.+?\\.(\\w+\\.[a-z]+)$" /> -->    
    </bean>
```

## CookieとIPアドレスの関係

試験環境にドメインがなかったので、
当初IPアドレスのみでむりやりクッキーのドメインを取得しようとしたが規格上うまくいかなかった。

### Cookieの規格

* [RFC-2109](https://www.ietf.org/rfc/rfc2109.txt)
  * クッキーとドメインの関係についての規格
  * `x.foo.com` に対して `.foo.com` というクッキーは正当
  * `.com`に対して`.com`というクッキーは内包する「.」がないので不正
  * というか範囲がでかすぎて[クッキーモンスター](https://en.wikipedia.org/wiki/Cookiemonster_attack)という脆弱性になる

```
4.3.2  Rejecting Cookies

   To prevent possible security or privacy violations, a user agent
   rejects a cookie (shall not store its information) if any of the
   following is true:

   * The value for the Path attribute is not a prefix of the request-
     URI.

   * The value for the Domain attribute contains no embedded dots or
     does not start with a dot.

   * The value for the request-host does not domain-match the Domain
     attribute.

   * The request-host is a FQDN (not IP address) and has the form HD,
     where D is the value of the Domain attribute, and H is a string
     that contains one or more dots.

   Examples:

   * A Set-Cookie from request-host y.x.foo.com for Domain=.foo.com
     would be rejected, because H is y.x and contains a dot.



Kristol & Montulli          Standards Track                     [Page 7]

RFC 2109            HTTP State Management Mechanism        February 1997


   * A Set-Cookie from request-host x.foo.com for Domain=.foo.com would
     be accepted.

   * A Set-Cookie with Domain=.com or Domain=.com., will always be
     rejected, because there is no embedded dot.

   * A Set-Cookie with Domain=ajax.com will be rejected because the
     value for Domain does not begin with a dot.
```

### CookieとIPアドレスについてPerl monkたちの意見

IPアドレスとCookieに関してはそれっぽい記述は以下ぐらいしか見つけられなかった

```
Fully-qualified host name (FQHN) means either the fully-qualified
   domain name (FQDN) of a host (i.e., a completely specified domain
   name ending in a top-level domain such as .com or .uk), or the
   numeric Internet Protocol (IP) address of a host.  The fully
   qualified domain name is preferred; use of numeric IP addresses is
   strongly discouraged.
```

なので、behaviorを見てみると

[Cookie set to IP number?](http://www.perlmonks.org/?node_id=128608)

>You *can* set a cookie to an IP address.
>You just cannot wildcard it! So while -domain=>'.289.11.63.71' is invalid, ->domain=>'289.11.63.71' is not
>(get rid of the period before the first set of numbers).

* IPアドレスに対してwildcardを用いるのは動かないようだ
* 同様にして、IPアドレスの前半`289.11.`までをドメインにするような処理はブラウザのほうで不正とみなされたのか動かなかった


### 結論

* 複数サーバ間でセッションを共有するときはドメインを取得してサブドメインとIPを割り当てるとうまくいく
    * 例）`a.example.com` と `b.example.com`
* サーバではなくコンテキストパス間のセッションの共有でも動く
    * クッキーのドメインが`localhost`になるから
    * 例）`localhost:8080/application-a` と `localhost:8080/application-b`

### サンプルコード

* [spring-session-xml](https://github.com/Hiroyuki-Nagata/spring-session-xml)