Cookie の設定
Cookie とは
HTTP Cookie の仕様 - MDN Web Docs より Cookie の定義を以下に引用します。
Cookie(ウェブ Cookie、ブラウザー Cookie とも呼ぶ)は、サーバーがユーザーのウェブブラウザーに送信する小さなデータです。ブラウザーは Cookie を保存したり、新しい Cookie を作成したり、既存の Cookie を変更したり、後でリクエストされたときに同じサーバーにそれらを送り返したりすることができます。 Cookie により、ウェブアプリケーションは限られた量のデータを格納し、状態についての情報を記憶することができます。
Cookie を使用する際には、 CSRF 攻撃のような脆弱性を悪用した脅威に対しアプリケーション側で対策を施す必要があります。 AlesInfiny Maia OSS Edition での CSRF 攻撃への対策の方針については、こちら を参照してください。
本章では、上記方針に基づき Cookie を利用する場合の設定方法について解説します。
バックエンドアプリケーションの設定
本章では、サンプルアプリケーションにて実装している、購入者 ID を Cookie へ付与する機能を設定例として解説します。
まず、 Cookie に付与する属性を application.properties
に定義します。 以下は、クロスオリジンの場合の方針に基づき Secure
と HttpOnly
、 SameSite = None
を定義する例です。
Cookie の属性の設定を定義する application.properties の設定例
application.properties |
---|
| # Cookie の設定
cookie.settings.same-site=None
cookie.settings.http-only=true
cookie.settings.secure=true
|
その後、 @ConfigurationProperties
を利用して application.properties
に記述した Cookie の設定値を読み込みます。 各フィールドには初期値が設定されていますが、 application.properties
に記述された設定が優先されます。
Cookie の設定値を保持する CookieSettings.java
CookieSettings.java |
---|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 | package com.dressca.web.consumer.security;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import lombok.Data;
/**
* Cookie の設定を格納するクラスです。
*/
@Component
@ConfigurationProperties(prefix = "cookie.settings")
@Data
public class CookieSettings {
private String sameSite = "Strict";
private boolean httpOnly = true;
private boolean secure = false;
private int expiredDays = 1;
}
|
次に、 Spring Boot で提供されている ResponseCookie を利用して Cookie に設定値を反映させます。
具体的には、以下のように設定した Cookie の情報(購入者 ID )と設定値を Set-Cookie
のヘッダーに付与するフィルターを実装します。
ResponseCookie を利用したサンプルアプリケーションの実装例
BuyerIdFilter.java |
---|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57 | package com.dressca.web.consumer.filter;
import java.io.IOException;
import java.util.UUID;
import jakarta.servlet.Filter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseCookie;
import com.dressca.web.consumer.security.CookieSettings;
/**
* 購入者 ID にフィルターをかけるクラスです。
*/
@AllArgsConstructor
public class BuyerIdFilter implements Filter {
private static final String DEFAULT_BUYER_COOKIE_NAME = "Dressca-Bid";
private static final String BUYER_ID_ATTRIBUTE_KEY = "buyerId";
private final CookieSettings cookieSettings;
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
Cookie[] cookies = ((HttpServletRequest) request).getCookies();
String buyerId = null;
if (cookies != null) {
for (Cookie cookie : cookies) {
if (cookie.getName().equals(DEFAULT_BUYER_COOKIE_NAME)) {
buyerId = cookie.getValue();
}
}
}
if (StringUtils.isBlank(buyerId)) {
buyerId = UUID.randomUUID().toString();
}
request.setAttribute(BUYER_ID_ATTRIBUTE_KEY, buyerId);
chain.doFilter(request, response);
buyerId = request.getAttribute(BUYER_ID_ATTRIBUTE_KEY).toString();
ResponseCookie responseCookie = ResponseCookie.from(DEFAULT_BUYER_COOKIE_NAME, buyerId)
.path("/")
.httpOnly(cookieSettings.isHttpOnly())
.secure(cookieSettings.isSecure())
.maxAge((long) cookieSettings.getExpiredDays() * 60 * 60 * 24)
.sameSite(cookieSettings.getSameSite()).build();
((HttpServletResponse) response).addHeader(HttpHeaders.SET_COOKIE, responseCookie.toString());
}
}
|
最後に、上記で実装したフィルターを Bean 登録します。
Cookie の設定を設定するフィルタークラスである DresscaWebConfig.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 | package com.dressca.web.consumer.config;
import com.dressca.web.consumer.filter.BuyerIdFilter;
import com.dressca.web.consumer.security.CookieSettings;
import jakarta.servlet.Filter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* Dressca Web 用の設定クラスです。
*/
@Configuration
public class DresscaWebConfig {
@Autowired
private CookieSettings cookieSettings;
/**
* 購入者 ID のフィルターを設定します。
*
* @return 購入者 ID のフィルター。
*/
@Bean
public FilterRegistrationBean<Filter> buyerIdFilter() {
FilterRegistrationBean<Filter> bean = new FilterRegistrationBean<>();
bean.setFilter(new BuyerIdFilter(this.cookieSettings));
return bean;
}
}
|
これにより、 Cookie に CSRF 対策を施すことができます。
フロントエンドアプリケーションの設定
クロスオリジンの環境の場合、フロントエンドアプリケーションでは、リクエスト発行時に Cookie をヘッダーに含めることを許可する設定が必要となります。 実装例は CORS 環境の構築 を参照してください。