春学期ガイド

1概要

Spring Session には、サーバーに保存されているHTTPセッションの制限からセッション管理を解放するという単純な目標があります。

このソリューションにより、単一のコンテナ(つまりTomcat)に縛られることなく、クラウド内のサービス間でセッションデータを共有することが簡単になります。

さらに、同じブラウザで複数のセッションをサポートし、ヘッダーでセッションを送信することもできます。

この記事では、Webアプリケーションで認証情報を管理するために Spring Session を使用します。 Spring Session はJDBC、Gemfire、またはMongoDBを使用してデータを永続化できますが、 Redis を使用します。

Redis の紹介については、リンクをチェックしてください:/spring-data-redis-tutorial[この]記事

** 2簡単なプロジェクト

**

最初に、後でセッション例のベースとして使用する簡単な Spring Boot プロジェクトを作成しましょう。

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.4.0.RELEASE</version>
    <relativePath/>
</parent>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

私たちのアプリケーションは Spring Boot で動作し、親pomは各エントリのバージョンを提供します。各依存関係の最新版は、ここにあります。

spring-boot -starter-security 、https://search.maven.org/classic/#search%7C1%7Cg%3A%22org.springframework.boot%22%20AND%20a%3A%22spring-boot-starter-web %22[spring-boot-starter-web]、https://search.maven.org/classic/#search%7Cgav%7C1%7Cg%3A%22org.springframework.boot%22%20AND%20a%3A%22spring -boot-starter-test%22[スプリングブートスターターテスト]。

application.properties にRedisサーバーの設定プロパティを追加しましょう。

spring.redis.host=localhost
spring.redis.port=6379

3スプリングブート設定

まず、Bootで Spring Session を設定する方法を説明しましょう。

注:セクション3と4を完了する必要はありません。 Spring Session を構成するために Spring Boot を使用しているかどうかに応じて1つを選択してください。

** 3.1. 依存関係

**

これらの依存関係を私たちのプロジェクトに追加してください。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.session</groupId>
    <artifactId>spring-session</artifactId>
</dependency>

ここではバージョンを設定するためにboot parent pomを使用しているので、これらは他の依存関係でも動作することが保証されています。各依存関係の最新版は、ここにあります。

spring -boot-starter-data-redis 、https://search.maven.org/classic/#search%7Cgav%7C1%7Cg%3A%22org.springframework.session%22%20AND%20a%3A%22spring-session %22[春セッション]。

3.2. Springセッション構成

それでは、 Spring Session の設定クラスを追加しましょう。

@Configuration
@EnableRedisHttpSession
public class SessionConfig extends AbstractHttpSessionApplicationInitializer {
}

** 4標準のSpring Config(起動なし)

**

Spring Bootを使わずに spring-session を統合して設定する方法も見てみましょう。

** 4.1. 依存関係

**

まず、標準のSpringプロジェクトに spring-session を追加する場合は、次のように明示的に定義する必要があります。

<dependency>
    <groupId>org.springframework.session</groupId>
    <artifactId>spring-session</artifactId>
    <version>1.2.2.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-redis</artifactId>
    <version>1.5.0.RELEASE</version>
</dependency>

これらのモジュールの最新版はここにあります。

spring-session 、https://search.maven.org/classic/#search%7Cgav%7C1%7Cg%3A%22org.springframework.data%22%20AND%20a%3A%22spring-data-redis%22[spring-data-redis]

4.2. Springセッション構成

それでは、 Spring Session の設定クラスを追加しましょう。

@Configuration
@EnableRedisHttpSession
public class SessionConfig extends AbstractHttpSessionApplicationInitializer {
    @Bean
    public JedisConnectionFactory connectionFactory() {
        return new JedisConnectionFactory();
    }
}

ごらんのとおり、違いはごくわずかです - JedisConnectionFactory Beanを明示的に定義しなければなりません - Bootがそれを行います。

両方の型で、 @ EnableRedisHttpSession および AbstractHttpSessionApplicationInitializer の拡張は、アクティブなセッションを探し、 Redis に格納された値からセキュリティコンテキストを生成するために、すべてのセキュリティインフラストラクチャの前にフィルタを作成して接続します。

それでは、コントローラとセキュリティ設定を使ってこのアプリケーションを完成させましょう。

5アプリケーション構成

メインのアプリケーションファイルに移動してコントローラを追加します。

@RestController
public class SessionController {
    @RequestMapping("/")
    public String helloAdmin() {
        return "hello admin";
    }
}

これは私達にテストするための終点を与えるでしょう。

次に、セキュリティ設定クラスを追加します。

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth
          .inMemoryAuthentication()
          .withUser("admin").password("password").roles("ADMIN");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
          .httpBasic().and()
          .authorizeRequests()
          .antMatchers("/").hasRole("ADMIN")
          .anyRequest().authenticated();
    }
}

これは私達のエンドポイントを基本認証で保護し、テストするユーザーを設定します。

6. テスト

最後に、すべてを試してみましょう。ここでは、2つのことを実行できるようにする簡単なテストを定義します。

  • ライブWebアプリケーションを使用する

  • Redisと話す

最初に設定しましょう。

public class SessionControllerTest {

    private Jedis jedis;
    private TestRestTemplate testRestTemplate;
    private TestRestTemplate testRestTemplateWithAuth;
    private String testUrl = "http://localhost:8080/";

    @Before
    public void clearRedisData() {
        testRestTemplate = new TestRestTemplate();
        testRestTemplateWithAuth = new TestRestTemplate("admin", "password", null);

        jedis = new Jedis("localhost", 6379);
        jedis.flushAll();
    }
}

HTTPクライアントとRedisクライアントの両方のクライアントを設定していることに注目してください。もちろん、この時点でサーバー(そしてRedis)は稼働しているはずです - これらのテストを通してそれらと通信できるように。

Redis が空であることをテストすることから始めましょう。

@Test
public void testRedisIsEmpty() {
    Set<String> result = jedis.keys("** ");
    assertEquals(0, result.size());
}

次に、認証されていない要求に対して私たちのセキュリティが401を返すことをテストします。

@Test
public void testUnauthenticatedCantAccess() {
    ResponseEntity<String> result = testRestTemplate.getForEntity(testUrl, String.class);
    assertEquals(HttpStatus.UNAUTHORIZED, result.getStatusCode());
}

次に、 Spring Session が認証トークンを管理していることをテストします。

@Test
public void testRedisControlsSession() {
    ResponseEntity<String> result = testRestTemplateWithAuth.getForEntity(testUrl, String.class);
    assertEquals("hello admin", result.getBody());//login worked

    Set<String> redisResult = jedis.keys("** ");
    assertTrue(redisResult.size() > 0);//redis is populated with session data

    String sessionCookie = result.getHeaders().get("Set-Cookie").get(0).split(";")[0];
    HttpHeaders headers = new HttpHeaders();
    headers.add("Cookie", sessionCookie);
    HttpEntity<String> httpEntity = new HttpEntity<>(headers);

    result = testRestTemplate.exchange(testUrl, HttpMethod.GET, httpEntity, String.class);
    assertEquals("hello admin", result.getBody());//access with session works worked

    jedis.flushAll();//clear all keys in redis

    result = testRestTemplate.exchange(testUrl, HttpMethod.GET, httpEntity, String.class);
    assertEquals(HttpStatus.UNAUTHORIZED, result.getStatusCode());
   //access denied after sessions are removed in redis
}

まず、このテストでは、管理者認証の資格情報を使用して、要求が成功したことを確認しました。

それから、レスポンスヘッダからセッション値を抽出し、それを2番目のリクエストの認証として使用します。それを検証してから、 Redis のすべてのデータを消去します。

最後に、セッションクッキーを使用して別のリクエストを行い、ログアウトしたことを確認します。これにより、 Spring Session がセッションを管理していることが確認されました。

7. 結論

Spring Session はHTTPセッションを管理するための強力なツールです。セッションストレージを設定クラスといくつかのMaven依存関係に単純化したので、複数のアプリケーションを同じ Redis インスタンスに接続して認証情報を共有することができます。

いつものように、あなたはソースコードhttps://github.com/eugenp/tutorials/tree/master/spring-session[Githubについて]を見つけることができる。