今回の目標
前回はUserDetailsの実装について説明しました。

今回はSpring Securityで行えるセッション管理とRemember Meについて説明をします。
セッションの設定
セッションに関する設定はプロパティとしてapplication.yml(properties)に設定します。これはSpring Bootの共通の設定なので、Spring Securityに関係なく設定できます。
プロパティについてはこちらを参考にしてください。

ここからセッションに関するものだけピックアップしておきます。
プロパティ | 説明 |
server.servlet.session.cookie.comment | セッションCookieのコメント。 |
server.servlet.session.cookie.domain | セッションCookieのドメイン。 |
server.servlet.session.cookie.http-only | HttpOnlyを使用するかどうか。 |
server.servlet.session.cookie.max-age | セッションCookieの最大有効期間(秒)。 |
server.servlet.session.cookie.name | セッションCookie名。 |
server.servlet.session.cookie.path | セッションCookieのパス。 |
server.servlet.session.cookie.secure | セキュアCookieを有効にするかどうか。 |
server.servlet.session.persistent | 再起動でセッションを保持するかどうか。 |
server.servlet.session.store-dir | セッションデータの保存に使用されるディレクトリ。 |
server.servlet.session.timeout | セッションタイムアウトの時間(デフォルトは30分)。 |
server.servlet.session.tracking-modes | セッション追跡モード。 |
セッションハイジャックへの対策として、本番リリース時はhttp-onlyとsecureはtrueに設定しておきましょう。
Spring Securityにおけるセッション管理
セッション管理に関する設定
セッション管理に関する設定は、毎度の如く設定クラスに記載していきます。
@Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() //略 .and() .sessionManagement(); }
セッションの生成
セッションの生成については以下の4パターンがあります。
生成方法 | 説明 |
always | 無条件に生成する。 |
ifRequired(デフォルト) | 必要な時に生成する。 |
never | 生成しない。ただし、存在する場合は利用する。 |
stateless | 生成せず、利用もしない。 |
あまりないとは思いますが、この設定を変更する場合は以下のようにします。
@Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() //略 .and() .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED); }
SessionCreationPolicyは列挙型になっているので適当なものを指定します。
URL Rewriting
URL Rewritingを有効にすることで以下のようにURLでセッションを管理できます。
http://localhost:8080/login;jsessionid=011F2A5B06EAB78299A9DB732DCDC9BB
しかし、セキュリティ的にはいろいろと問題があるのでSpring Securityではデフォルトで無効になっています。
有効化することもできますが、いろいろと手順があり面倒なのでここでは割愛します。
CSRF対策
こちらの記事でも記載した通り、Spring SecurityではCSRF対策としてセッションに一時トークンが登録されます。

そのためすべてのページでセッションが生成されます。
不要な場合は、以下のようにすることで特定のページ対し除外することができます。以下の例ではH2 Databaseのコンソールに対するパスについて除外しています。
@Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() //略 .and() .csrf().ignoringAntMatchers("/h2-console/**"); }
セッション固定化攻撃対策
セッション固定化攻撃については以下を参考にしてください。

この攻撃方法には、ログイン後にセッションIDを再発行することが最も有効な対策となります。
Spring Securityではこの対策もデフォルトで実装されています。ブラウザで確認すると以下のようにログイン後にセッションIDが変わっていることが分かります。
これを無効化することはないかもしれませんが、以下で無効化できます。
@Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() //略 .and() .sessionManagement().sessionFixation().none(); }
セッションタイムアウト
セッションタイムアウトの設定は先述したようにプロパティファイルに設定します。
セッションがタイムアウトしたときのリダイレクト先は以下で設定できます。
@Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests().antMatchers("/timeout").permitAll() //略 .and() .sessionManagement().sessionFixation().invalidSessionUrl("/timeout");
あらかじめコントローラーに「/timeout」を実装し、permitAll()を設定しておきます。
この設定は、正確にはセッションが無効の場合の設定になります。とはいえほとんどがセッションタイムアウトのような気がするのでこれでも良いかなという感じです(私見)。
Remember Me
セッションに関わるところとしてRemember Meについて説明をしておきます。Remember Meは、ログイン情報をCookieに保存しておき、次回以降のログインを省略するための仕組みです。いわゆる自動ログインです。
Spring SecurityでRemember Meを実装するためには、以下のように設定クラスを変更します。
@Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() //略 .and() .rememberMe(); }
次にログイン画面にRemember Me用のチェックボックスを配置します。name属性を「remember-me」とする点がポイントです。
<input type="checkbox" name="remember-me">Remember Me
では追加したチェックボックスにチェックを入れてログインしてみましょう。そしてブラウザを一度閉じてログイン後のページにアクセスできるか確認してみてください。
Cookieを確認すると、「remember-me」という名前の値が保存されています。この値にはログイン情報などがハッシュ化された状態で保存されます。
ちなみにログアウトするとこのCookieは破棄されます。
Keyの設定
上述したハッシュ化にはKeyとなる値が使用されています。デフォルトでは、Spring Securityがサーバー起動時にランダムな値を生成し、ハッシュ時に使用するようになっています。
つまり再起動をすると、Cookieに保存している値とサーバー側の値が異なるものになってしまい、自動ログインは解除されます。
これを解消するためには、Key値を以下のように固定化します。値は安全なランダム値を使用するのがいいかと思います。
@Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() //略 .and() .rememberMe().key("hogehoge"); }
パラメーター名の設定
Remember Meを実装するにあたり、remember-meパラメーターを送信するようにログイン画面を修正しました。このパラメーター名は以下のようにすることで変更することができます。
@Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() //略 .and() .rememberMe().rememberMeParameter("hogehoge"); }
常に保存するようにする
remember-meパラメーターを送信せずとも、常にログイン情報を保存したい場合は以下のようにします。
@Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() //略 .and() .rememberMe().alwaysRemember(true); }
Cookie情報の設定
Remember Meを保存するCookieについて、ドメイン、名前、Max-Age、Secure属性を以下のように設定することができます。
@Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() //略 .and() .rememberMe().rememberMeCookieDomain("hogehoge") .rememberMeCookieName("fugafuga") .tokenValiditySeconds(1209600) .useSecureCookie(true); }
Max-Ageは秒で指定し、デフォルトでは14日が設定されているようです。
実際に本番環境で使用する場合は、これらの設定はしておいたほうが良いかと思います。
Secure属性については、開発環境で有効にすると動作しなくなるので、プロパティファイルで制御するなど工夫することをおすすめします。
あとがき
さて、今回はセッションに関することを説明してきました。実は他にも設定はあるのですが今回はこのくらいにしておきます。
セッションはセキュリティー的に重要な部分でもあるので、デフォルトでいろいろ対策されているのは大変ありがたいことです。
- Spring Bootのおすすめ書籍はコチラ -
コメント