Spring Security - キャッシュコントロールヘッダ

1.はじめに

この記事では、Spring SecurityでHTTPキャッシングを制御する方法を探ります。

デフォルトの動作を説明し、その背後にある理由も説明します。次に、この動作を部分的または完全に変更する方法を検討します。

2.デフォルトのキャッシュ動作

キャッシュ制御ヘッダーを効果的に使用することによって、リソースをキャッシュし、ネットワークホップを回避するようにブラウザに指示することができます。これにより待ち時間が減り、サーバーの負荷も減ります。

デフォルトでは、Spring Securityは特定のキャッシュ制御ヘッダ値を設定します。何も設定する必要はありません。

まず、Spring Securityをアプリケーション用に設定しましょう。

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {}
}

何もしないように configure() をオーバーライドしています。つまり、エンドポイントにアクセスするために認証を受ける必要がないため、純粋にキャッシュのテストに集中することができます。

次に、簡単なRESTエンドポイントを実装しましょう。

@GetMapping("/default/users/{name}")
public ResponseEntity<UserDto> getUserWithDefaultCaching(@PathVariable String name) {
    return ResponseEntity.ok(new UserDto(name));
}

結果の cache-control ヘッダーは次のようになります。

----[cache-control: no-cache, no-store, max-age=0, must-revalidate]----

最後に、エンドポイントにヒットするテストを実装し、レスポンスでどのヘッダーが送信されるかを表明しましょう。

given()
  .when()
  .get(getBaseUrl() + "/default/users/Michael")
  .then()
  .header("Cache-Control", "no-cache, no-store, max-age=0, must-revalidate")
  .header("Pragma", "no-cache");

基本的に、これが意味するのはブラウザがこの応答を決してキャッシュしないということです。

これは非効率的に思えるかもしれませんが、実際にはこのデフォルトの振る舞いには正当な理由があります。** 1人のユーザーがログアウトして別のユーザーがログインした場合デフォルトでは何もキャッシュしない方がはるかに安全であり、キャッシュを明示的に有効にする責任を負うのは私たちの責任です。

3.デフォルトのキャッシュ動作を上書きする

時には、キャッシュしたいリソースを扱っているかもしれません。有効にする場合は、リソースごとに行うのが最も安全でしょう。これは、他のリソースがデフォルトでまだキャッシュされないことを意味します。

これを行うには、 CacheControl キャッシュ。 CacheControl クラスは流暢なビルダーであるため、さまざまなタイプのキャッシュを簡単に作成できます。

@GetMapping("/users/{name}")
public ResponseEntity<UserDto> getUser(@PathVariable String name) {
    return ResponseEntity.ok()
      .cacheControl(CacheControl.maxAge(60, TimeUnit.SECONDS))
      .body(new UserDto(name));
}

テストでこのエンドポイントをヒットし、ヘッダーを変更したことを表明します。

given()
  .when()
  .get(getBaseUrl() + "/users/Michael")
  .then()
  .header("Cache-Control", "max-age=60");

ご覧のとおり、デフォルトは無効にされており、今度はブラウザからの応答が60秒間キャッシュされます。

4.デフォルトのキャッシュ動作を無効にする

Spring Securityのデフォルトのキャッシュコントロールヘッダを完全に無効にすることもできます。これは非常に危険なことであり、実際には推奨されません。しかし、本当にやりたければ、 WebSecurityConfigurerAdapterの configure__メソッドをオーバーライドして試すことができます。

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.headers().disable();
}

それでは、もう一度エンドポイントにリクエストを送信して、どのようなレスポンスが返されるのかを確認しましょう。

given()
  .when()
  .get(getBaseUrl() + "/default/users/Michael")
  .then()
  .headers(new HashMap<String, Object>());

ご覧のとおり、キャッシュヘッダはまったく設定されていません。繰り返しますが、これは安全ではありませんが、必要に応じてデフォルトのヘッダーを無効にする方法を証明しています。

7.まとめ

この記事では、Spring SecurityがデフォルトでHTTPキャッシングを無効にする方法を説明し、これが安全なリソースをキャッシュしたくないためであることを説明します。また、この動作を無効にしたり変更したりする方法についても説明しました。

これらすべての例とコードスニペットの実装はhttps://github.com/eugenp/tutorials/tree/master/spring-security-cache-control[GitHubプロジェクト]にあります - これはMavenプロジェクトです。インポートしてそのまま実行するのは簡単なはずです。

前の投稿:Java Web Weekly、第131号
次の投稿:ElasticSearchによる全文検索の概要