JavaのSprigBootで組み込みTomcat使用時に、Cookie、特にJSESSIONIDにSameSite属性を設定するときに、予想外に苦労したので、苦労話と設定方法を載せておきます。
目次
JavaのサーブレットAPIの4.0仕様では、SessionにSameSiteを実装していない
驚きなのですが、CORS対応時代であり、この記事を書いている時点で、JavaのサーブレットAPIの仕様では、SessionクラスはSameSiteを持っているように実装されていません。
なので、SessionCookieConfigで簡単に設定する……というわけにはいきませんでした。
webサーバーの設定ファイルでSameSite属性を付けるように変更する方法
webサーバーの設定ファイルでJSESSIONIDを書き換える方法は、下記の記事に書かれていましたが、組み込みTomcatのjar形式でコードを書いていたので、この方法は適用できませんでした。
SpringBootのTomcatContextCustomizerでCookieProcessorを使ってSameSite属性を設定する
SpringBootのTomcatContextCustomizerというクラスでCookieProcessorを使ってSameSite属性を設定する方法が下記の記事で紹介されていました。
この方法だと、私の環境下だとなぜか機能しなかったということと、意味はないけれど、JSESSIONIDのように特定のCookieのみにSameSite属性を付けられる方法ではなさそうだったので、諦めました。
SpringSessionならデフォルトでSameSite属性が設定されているので使う
さっきの記事で紹介されているように、SpringSessionならデフォルトでSameSite属性が設定されているので、おとなしく SpringSession を使うのがよい気がします。
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の設定で参考にしたページ一覧