この記事を参考にしながらSpring-Sessionを試してみた
特に、アノテーションではなくXMLベースでの設定をやりたかった。
Spring-sessionのドキュメント
公式ドキュメントにXMLでの設定例が載っている。
最終的なBeanの設定
- web.xmlの設定は必須なので、他の記事を参考にして設定してください
-
Beanの設定は次のブログを参考にした spring-session学习
- 中国語なので詳しくはわからないが、クッキーの生成されるタイミングも含めて詳しい解説がある
次のブログにある設定を試している Spring-session & redis 子域名共享session
この設定を適用すると
-
cookieName
: デフォルトのCookie名を上書きできる -
domainNamePattern
: 正規表現で複数ドメインを1つのドメインとみなしてクッキーを発行できる- 例えば
a.example.com
,b.example.com
は下の正規表現でキャプチャーするとexample.com
になる - 検証コード → Wandbox
- ということは、複数サーバ間でセッションを共有できる
- 英語で調べるときは「session replicate」もしくは「session clustering」で検索するとよさそうだ。
- 例えば
-
domainName
: 正規表現を使わずにホスト名を直接指定する(domainNamePatternでうまく動かないときは、こちらを使ったほうがいいかもしれない)<property name="domainName" value=".example.com"/>
<!-- 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
- クッキーとドメインの関係についての規格
-
x.foo.com
に対して.foo.com
というクッキーは正当 -
.com
に対して.com
というクッキーは内包する「.」がないので不正 - というか範囲がでかすぎてクッキーモンスターという脆弱性になる
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を見てみると
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
- クッキーのドメインが