Spring Session - REST

このガイドでは、REST エンドポイントを使用するときに、Spring Session を使用して Redis を透過的に活用し、Web アプリケーションの HttpSession をバックアップする方法について説明します。

依存関係の更新

Spring Session を使用する前に、依存関係を更新する必要があります。Maven を使用する場合は、次の依存関係を追加する必要があります。

pom.xml
<dependencies>
	<!-- ... -->

	<dependency>
		<groupId>org.springframework.session</groupId>
		<artifactId>spring-session-data-redis</artifactId>
		<version>3.3.1</version>
		<type>pom</type>
	</dependency>
	<dependency>
		<groupId>io.lettuce</groupId>
		<artifactId>lettuce-core</artifactId>
		<version>6.3.2.RELEASE</version>
	</dependency>
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-web</artifactId>
		<version>6.1.9</version>
	</dependency>
</dependencies>

Spring の設定

必要な依存関係を追加した後、Spring 構成を作成できます。Spring 構成は、HttpSession 実装を Spring Session による実装に置き換えるサーブレットフィルターの作成を担当します。これを行うには、次の Spring 構成を追加します。

@Configuration
@EnableRedisHttpSession (1)
public class HttpSessionConfig {

	@Bean
	public LettuceConnectionFactory connectionFactory() {
		return new LettuceConnectionFactory(); (2)
	}

	@Bean
	public HttpSessionIdResolver httpSessionIdResolver() {
		return HeaderHttpSessionIdResolver.xAuthToken(); (3)
	}

}
1@EnableRedisHttpSession アノテーションは、Filter を実装する springSessionRepositoryFilter という名前の Spring Bean を作成します。このフィルターは、Spring Session によってサポートされる HttpSession 実装の置き換えを担当します。この場合、Spring Session は Redis によってサポートされています。
2Spring Session を Redis サーバーに接続する RedisConnectionFactory を作成します。デフォルトのポート (6379) でローカルホストに接続するように接続を構成します。Spring Data Redis の構成の詳細については、リファレンスドキュメントを参照してください
3Spring Session の HttpSession 統合をカスタマイズして、Cookie の代わりに HTTP ヘッダーを使用して現在のセッション情報を伝達します。

サーブレットコンテナーの初期化

Spring の設定は、Filter を実装する springSessionRepositoryFilter という名前の Spring Bean を作成しました。springSessionRepositoryFilter Bean は、HttpSession を Spring Session によるカスタム実装に置き換えるロールを果たします。

Filter がその魔法を実行するために、Spring は Config クラスをロードする必要があります。次の例に示すように、Spring MvcInitializer で構成を提供します。

src/main/java/sample/mvc/MvcInitializer.java
@Override
protected Class<?>[] getRootConfigClasses() {
	return new Class[] { SecurityConfig.class, HttpSessionConfig.class };
}

最後に、サーブレットコンテナー(つまり、Tomcat)がすべてのリクエストに springSessionRepositoryFilter を使用するようにする必要があります。幸い、Spring Session には、AbstractHttpSessionApplicationInitializer という名前のユーティリティクラスが用意されており、これを簡単に実行できます。これを行うには、次の例に示すように、デフォルトのコンストラクターを使用してクラスを継承します。

src/main/java/sample/Initializer.java
public class Initializer extends AbstractHttpSessionApplicationInitializer {

}
クラスの名前(Initializer)は関係ありません。重要なのは、AbstractHttpSessionApplicationInitializer を継承することです。

rest サンプルアプリケーション

このセクションでは、rest サンプルアプリケーションの使用方法について説明します。

rest サンプルアプリケーションの実行

サンプルを実行するには、ソースコードを取得し、次のコマンドを呼び出します。

サンプルを機能させるには、ローカルホストで Redis 2.8+ をインストールします (英語) を実行し、デフォルトのポート (6379) で実行する必要があります。または、Redis サーバーを指すように RedisConnectionFactory を更新することもできます。もう 1 つのオプションは、Docker (英語) を使用してローカルホストで Redis を実行することです。詳細な手順については、Docker Redis リポジトリ (英語) を参照してください。
$ ./gradlew :spring-session-sample-javaconfig-rest:tomcatRun

これで、localhost:8080/ でアプリケーションにアクセスできるようになります。

rest サンプルアプリケーションの探索

これで、アプリケーションの使用を試みることができます。これを行うには、お気に入りの REST クライアントを使用して localhost:8080/ をリクエストします

	$ curl -v http://localhost:8080/

基本認証の入力を求められることに注意してください。ユーザー名とパスワードについて、次の情報を入力してください。

  • ユーザー名 user

  • パスワード password

次に、次のコマンドを実行します。

$ curl -v http://localhost:8080/ -u user:password

出力では、次のことに注意してください。

HTTP/1.1 200 OK
...
X-Auth-Token: 0dc1f6e1-c7f1-41ac-8ce2-32b6b3e57aa3

{"username":"user"}

具体的には、私たちの対応について次のことに注意する必要があります。

  • HTTP ステータスは 200 になりました。

  • X-Auth-Token という名前のヘッダーがあり、新しいセッション ID が含まれています。

  • 現在のユーザー名が表示されます。

これで、X-Auth-Token を使用して、ユーザー名とパスワードを再度入力しなくても、別のリクエストを行うことができます。例: 次のコマンドは、前と同じようにユーザー名を出力します。

	$ curl -v http://localhost:8080/ -H "X-Auth-Token: 0dc1f6e1-c7f1-41ac-8ce2-32b6b3e57aa3"

唯一の違いは、既存のセッションを再利用しているため、セッション ID がレスポンスヘッダーに指定されていないことです。

セッションを無効にすると、レスポンスに X-Auth-Token が空の値で表示されます。例: 次のコマンドはセッションを無効にします:

	$ curl -v http://localhost:8080/logout -H "X-Auth-Token: 0dc1f6e1-c7f1-41ac-8ce2-32b6b3e57aa3"

出力で、X-Auth-Token が前のセッションが無効化されたことを示す空の String を提供していることがわかります。

HTTP/1.1 204 No Content
...
X-Auth-Token:

それはどのように機能しますか?

Spring Security は、SecurityContextPersistenceFilter の標準 HttpSession と相互作用します。

Tomcat の HttpSession を使用する代わりに、Spring Security は Redis の値を永続化するようになりました。Spring Session は、ブラウザーに X-Auth-Token という名前のヘッダーを作成します。そのヘッダーには、セッションの ID が含まれています。

必要に応じて、セッションが Redis で作成されていることが簡単にわかります。これを行うには、次のコマンドを使用してセッションを作成します。

$ curl -v http://localhost:8080/ -u user:password

出力では、次のことに注意してください。

HTTP/1.1 200 OK
...
X-Auth-Token: 7e8383a4-082c-4ffe-a4bc-c40fd3363c5e

{"username":"user"}

これで、redis-cli を使用してセッションを削除できます。例: Linux ベースのシステムでは、次のように入力できます。

	$ redis-cli keys '*' | xargs redis-cli del
Redis のドキュメントには、redis-cli のインストール (英語) 手順が記載されています。

または、明示的なキーを削除することもできます。これを行うには、ターミナルに次のように入力します。必ず 7e8383a4-082c-4ffe-a4bc-c40fd3363c5e を SESSION Cookie の値に置き換えてください。

	$ redis-cli del spring:session:sessions:7e8383a4-082c-4ffe-a4bc-c40fd3363c5e

これで、X-Auth-Token を使用して、削除したセッションで別のリクエストを行い、認証のプロンプトが表示されることを確認できます。例: 以下は HTTP401 を返します。

	$ curl -v http://localhost:8080/ -H "X-Auth-Token: 0dc1f6e1-c7f1-41ac-8ce2-32b6b3e57aa3"