SpringBootでTomcat使用時においてCookieのセッション(JSESSIONID)にSameSite属性を設定する方法

JavaのSprigBootで組み込みTomcat使用時に、Cookie、特にJSESSIONIDにSameSite属性を設定するときに、予想外に苦労したので、苦労話と設定方法を載せておきます。

JavaのサーブレットAPIの4.0仕様では、SessionにSameSiteを実装していない

驚きなのですが、CORS対応時代であり、この記事を書いている時点で、JavaのサーブレットAPIの仕様では、SessionクラスはSameSiteを持っているように実装されていません。

なので、SessionCookieConfigで簡単に設定する……というわけにはいきませんでした。

webサーバーの設定ファイルでSameSite属性を付けるように変更する方法

webサーバーの設定ファイルでJSESSIONIDを書き換える方法は、下記の記事に書かれていましたが、組み込みTomcatのjar形式でコードを書いていたので、この方法は適用できませんでした。

Apache Tomcat連携サーバで、CookieにSameSite属性を設定する方法 - Qiita
2/17以降にGoogle Chromeを使って、 「①あるドメインのURL」→(POST or GET)→ 「②別ドメインのURL」→(POST)→ 「③元のドメインのURL」 の順でページ遷移した場合、セッションが切れるように仕様...
Setting the SameSite Attribute on the JSESSIONID cookie for Java based deployments
SameSite is a requirement in latest Chrome starting Feb 2020 Read a very good and easy-to-understand explainer on SameSite Turns out none of  Java-based ecosyst...

SpringBootのTomcatContextCustomizerでCookieProcessorを使ってSameSite属性を設定する

SpringBootのTomcatContextCustomizerというクラスでCookieProcessorを使ってSameSite属性を設定する方法が下記の記事で紹介されていました。

Spring Boot(Spring Web MVC + Tomcat)におけるSameSite Cookie - Qiita
Spring Boot(Spring Web MVC + Tomcat)でSameSite Cookieを使うにはどのようにすればいいか、調べてみました。 SameSite Cookieとはなにか MDNのドキュメントを参照して...

この方法だと、私の環境下だとなぜか機能しなかったということと、意味はないけれど、JSESSIONIDのように特定のCookieのみにSameSite属性を付けられる方法ではなさそうだったので、諦めました。

SpringSessionならデフォルトでSameSite属性が設定されているので使う

さっきの記事で紹介されているように、SpringSessionならデフォルトでSameSite属性が設定されているので、おとなしく SpringSession を使うのがよい気がします。

spring-projects/spring-session
Spring Session. Contribute to spring-projects/spring-session development by creating an account on GitHub.

Filter処理でSessionを書き換えてSameSite属性を設定する

SpringSession入れたり、クラスカスタマイズするほどじゃない、
少しSessionにSameSite属性とか気軽に設定できればいいんだ、
どうせそのうち対応されるだろうから、もっとバカな方法でいいんだ、
とダメなことを考える人には、Filter処理でSessionを書き換えてSameSite属性を設定する方法を紹介しておきます。

Filter処理(Filterクラスを実装する方法)でServletResponseをリフレッシュしてから、手動でヘッダーにセッションを設定し直すという方法です。

ServletResponseをリフレッシュするのは、setHeaderやaddHeaderはあっても、deleteHeaderやremoveHeaderみたいに、すでにあるヘッダー(ここではセッションのCookie)をどうにかする方法が、これまた不便ですが用意されていないので、コミットされる前の ServletResponse を一度リフレッシュすることで、Sessionのcookieを設定し直すとう方法です。

    HttpSession session = ((HttpServletRequest) request).getSession();
    String sessionId = session.getId();
    response.reset();
    ((HttpServletResponse) response).setHeader(HttpHeaders.SET_COOKIE, "JSESSIONID=" + sessionId + "; SameSite=None;  Httponly; Secure");

一応はこの方法でも、JSESSIONIDにSameSite属性を設定できて、CORSでも問題なくセッション維持ができました。

JavaのSESSION,Cookieの設定で参考にしたページ一覧

How to set SameSite and Secure attribute to JSESSIONID cookie
I have a Spring Boot Web Application (Spring boot version 2.0.3.RELEASE) and running in an Apache Tomcat 8.5.5 server. With the recent security policy which has...
SameSite cookie in Java application
JavaでCookieにSameSite属性をつける - Qiita
(20/01/08 19:45追記) 概要 javax.servlet.http.CookieにはSameSite属性を付与するAPIがありません。 そんな時の対応です。 ちなみにSameSite属性はほぼ全てのブラウザが対応し...
SessionCookieConfig (Servlet 3.1 API Documentation - Apache Tomcat 8.0.53)
Same-Site flag for session cookie in Spring Security
Is it possible to set Same-site Cookie flag in Spring Security? And if not, is it on a roadmap to add support, please? There is already support in some browser...
SameSite cookie in Java application
Do you know any Java cookie implementation which allows to set a custom flag for cookie, like SameSite=strict? It seems that javax.servlet.http.Cookie has a str...

タイトルとURLをコピーしました