spring.svg

【Spring Boot】セッションとCookie

SpringBoot

セッション

Spring Boot でセッションと取り扱う方法はいくつかあります。 セッションの取り扱いについて、ControllerRestControllerに違いはありません。

RESTful API の場合、ステートレスの観点からセッションを使用することはありません。 しかし、SPA などの実装の都合上、どうしてもセッションを使った方がよいケースがあります。

HttpSession

通常の Servlet で使用するHttpSessionを使用します。 HttpSessionは DI コンテナから参照します。

セッションを再生成する場合は、破棄してからHttpServletRequestgetSession()を使用します。

@RestController
public class SampleController {
  @Autowired
  private HttpSession session;

  @GetMapping
  public Object getData() {
    //セッションデータ取得
    return session.getAttribute("data");
  }

  @PostMapping
  public void setData(@RequestBody SampleData data, HttpServletRequest request) {
    //セッション再生成
    session.invalidate();
    session = request.getSession()
    //セッションデータ設定
    session.setAttribute("data", data);
  }
}

@SessionScope

以下のように@SessionScopeを設定した Bean を作成します。 これにより DI のスコープがセッションに設定されます。

@Component
@SessionScope
public class SessionData implements Serializable {
  private static final long serialVersionUID = 808198990406616280L;
  private SampleData sampleData;
  //コンストラクター・ゲッター・セッターは省略
}
@RestController
public class SampleController {
  @Autowired
  private SessionData sessionData;

  @GetMapping
  public SampleData getData() {
    //セッションデータ取得
    return sessionData.getSampleData();
  }

  @PostMapping
  public void setData(@RequestBody SampleData data) {
    //セッションデータ設定
    sessionData.setSampleData(data);
  }
}

上記の場合、セッションにはscopedTarget.sessionDataという名前で登録されます。

@SessionScopeは以下の@Scopeの設定と同義です。

@Scope(value="session", proxyMode=ScopedProxyMode.TARGET_CLASS)

@SessionAttributes

Controller ごとにセッションで使用するオブジェクトを@SessionAttributesで指定します。

@RestController
@SessionAttributes(types = SampleData.class)
public class SampleController {
  @ModelAttribute("sampleData")
  private SampleData setSampleData() {
    return new SampleData();
  }

  @GetMapping
  public SampleData getData(@ModelAttribute SampleData sampleData) {
    //セッションデータ取得
    return sampleData;
  }

  @PostMapping
  public void setData(@RequestBody SampleData data, @ModelAttribute SampleData sampleData) {
    //セッションデータ設定(ディープコピー)
    sampleData.clone(data);
  }
}

@ModelAttribute("sampleData")のメソッドによって、コントローラーアクセス時にsampleDataという名前でオブジェクトをセッションに登録します。 登録したオブジェクトは、@ModelAttributeを付与したパラメーターによって参照することができます。

複数のオブジェクトを使用したい場合も考え方は基本同じです。

@RestController
@SessionAttributes(types = {SampleData.class, SampleData2.class})
public class SampleController {
  @ModelAttribute("sampleData")
  private SampleData setSampleData() {
    return new SampleData();
  }

  @ModelAttribute("sampleData2")
  private SampleData2 setSampleData2() {
    return new SampleData2();
  }

  @GetMapping
  public SampleData getData(@ModelAttribute SampleData sampleData) {
    return sampleData;
  }

  @GetMapping
  public SampleData2 getData2(@ModelAttribute SampleData2 sampleData) {
    return sampleData2;
  }
}

プロパティ

セッションについて、application.yml.properties)に以下のプロパティが用意されています。

プロパティデフォルト説明
server.servlet.session.persistentfalse再起動時にセッションを保持するか
server.servlet.session.store-dirセッションの保存先フォルダ
server.servlet.session.timeout30mセッションタイムアウトの時間
server.servlet.session.tracking-modesセッション追跡モード
server.servlet.session.cookie.nameJSESSIONIDセッション Cookie 名
server.servlet.session.cookie.http-onlytrueセッション Cookie の HttpOnly 設定
server.servlet.session.cookie.securefalseセッション Cookie の Secure 設定
server.servlet.session.cookie.max-ageセッション Cookie の Max-Age 設定
server.servlet.session.cookie.domainセッション Cookie の Domain 設定
server.servlet.session.cookie.pathセッション Cookie の Path 設定
server.servlet.session.cookie.commentセッション Cookie のコメント

Cookie についてはこちらの記事を参考にしてください。

設定

Cookie を設定するには、Cookieオブジェクトを作成してレスポンスボディに追加します。 Cookieオブジェクトの生成には、キーと値のセットを指定します。

@PostMapping
public void setCookie(HttpServletResponse response) {
  Cookie cookie = new Cookie("key", "value");
  response.addCookie(cookie);
}

各属性の設定は、Cookieの以下のメソッドによって行います。

属性メソッド
Http-OnlysetHttpOnly()boolean
SecuresetSecure()boolean
Max-AgesetMaxAge()int
DomainsetDomain()String
PathsetPath()String
CommentsetComment()String

取得

Cookie を取得するには、@CookieValueを付与したパラメーターを指定します。

@GetMapping
public String getCookie(@CookieValue(name="key", required=false, defaultValue="none") String value) {
  return value;
}

@CookieValueには以下のプロパティがあります。

プロパティ説明
name取得する Cookie の名前
requiredtrueの場合、Cookie が存在しなければMissingRequestCookieExceptionをスローする
defaultValuerequiredfalseで、Cookie が存在しない場合の代わりの値

SameSite について

Cookieには SameSite の設定がありません。 SameSite の設定が必要な場合は、ResponseCookieを使用します。 以下のように、ResponseCookieSet-Cookieに設定する文字列を生成するためのジェネレーターです。

@PostMapping
public void setCookie(HttpServletResponse response) {
  ResponseCookie cookie = ResponseCookie.from("key", "set")
                                        .httpOnly(true)
                                        .secure(false)
                                        .sameSite(SameSite.LAX.attribute())
                                        .build();
  response.addHeader("Set-Cookie", cookie.toString());
}