Sessão de primavera com MongoDB

Sessão de primavera com MongoDB

1. Visão geral

Neste tutorial rápido, iremos explorar como usar a Spring Session apoiada emMongoDB, com e sem Spring Boot.

O Spring Session também pode ser feito com outros armazenamentos, comoRediseJDBC.

2. Configuração de inicialização do Spring

Primeiro, vamos dar uma olhada nas dependências e na configuração necessária para o Spring Boot. Para começar, vamos adicionar as versões mais recentes despring-session-data-mongodb espring-boot-starter-data-mongodb ao nosso projeto:


    org.springframework.session
    spring-session-data-mongodb
    2.1.5.RELEASE


    org.springframework.boot
    spring-boot-starter-data-mongodb
    2.1.8.RELEASE

Depois disso, para habilitar a configuração automática do Spring Boot, precisaremos adicionar o tipo de armazenamento Spring Session comomongodb emapplication.properties:

spring.session.store-type=mongodb

3. Configuração Spring sem Spring Boot

Agora, vamos dar uma olhada nas dependências e na configuração necessária para armazenar a sessão Spring no MongoDB sem Spring Boot.

Semelhante à configuração do Spring Boot, precisaremos da dependênciaspring-session-data-mongodb. No entanto, aqui usaremos a dependênciaspring-data-mongodb para acessar nosso banco de dados MongoDB:


    org.springframework.session
    spring-session-data-mongodb
    2.1.5.RELEASE


    org.springframework.data
    spring-data-mongodb
    2.1.8.RELEASE

Por fim, vamos ver como configurar o aplicativo:

@EnableMongoHttpSession
public class HttpSessionConfig {

    @Bean
    public JdkMongoSessionConverter jdkMongoSessionConverter() {
        return new JdkMongoSessionConverter(Duration.ofMinutes(30));
    }
}

The @EnableMongoHttpSession annotation enables the configuration required to store the session data in MongoDB.

Além disso, observe queJdkMongoSessionConverter é responsável por serializar e desserializar os dados da sessão.

4. Exemplo de aplicação

Vamos criar um aplicativo para testar as configurações. Estaremos usando Spring Boot, pois é mais rápido e requer menos configuração.

Começaremos criando o controlador para lidar com as solicitações:

@RestController
public class SpringSessionMongoDBController {

    @GetMapping("/")
    public ResponseEntity count(HttpSession session) {

        Integer counter = (Integer) session.getAttribute("count");

        if (counter == null) {
            counter = 1;
        } else {
            counter++;
        }

        session.setAttribute("count", counter);

        return ResponseEntity.ok(counter);
    }
}

Como podemos ver neste exemplo, estamos incrementandocounter em cada ocorrência para o endpoint e armazenando seu valor em um atributo de sessão denominadocount.

5. Testando o aplicativo

Vamos testar o aplicativo para ver se podemos realmente armazenar os dados da sessão no MongoDB.

Para fazer isso, acessaremos o endpoint e inspecionaremos o cookie que receberemos. Isso conterá um ID de sessão.

Depois disso, consultaremos a coleção do MongoDB para buscar os dados da sessão usando o ID da sessão:

@Test
public void
  givenEndpointIsCalledTwiceAndResponseIsReturned_whenMongoDBIsQueriedForCount_thenCountMustBeSame() {

    HttpEntity response = restTemplate
      .exchange("http://localhost:" + 8080, HttpMethod.GET, null, String.class);
    HttpHeaders headers = response.getHeaders();
    String set_cookie = headers.getFirst(HttpHeaders.SET_COOKIE);

    Assert.assertEquals(response.getBody(),
      repository.findById(getSessionId(set_cookie)).getAttribute("count").toString());
}

private String getSessionId(String cookie) {
    return new String(Base64.getDecoder().decode(cookie.split(";")[0].split("=")[1]));
}

6. Como funciona?

Vamos dar uma olhada no que acontece na sessão de primavera nos bastidores.

OSessionRepositoryFilter é responsável pela maior parte do trabalho:

  • converteHttpSession emMongoSession

  • verifica se há umCookie presente e, em caso afirmativo, carrega os dados da sessão da loja

  • salva os dados da sessão atualizados na loja

  • verifica a validade da sessão

Além disso,SessionRepositoryFilter cria um cookie com o nomeSESSION que é HttpOnly e seguro. Este cookie contém o ID da sessão, que é um valor codificado em Base64.

Para personalizar o nome ou as propriedades do cookie, teremos que criar um bean Spring do tipoDefaultCookieSerializer.

Por exemplo, aqui estamos desativando a propriedadehttponly do cookie:

@Bean
public DefaultCookieSerializer customCookieSerializer(){
    DefaultCookieSerializer cookieSerializer = new DefaultCookieSerializer();

    cookieSerializer.setUseHttpOnlyCookie(false);

    return cookieSerializer;
}

7. Detalhes da sessão armazenados no MongoDB

Vamos consultar nossa coleção de sessão usando o seguinte comando em nosso console MongoDB:

db.sessions.findOne()

Como resultado, obteremos um documentoBSON semelhante a:

{
    "_id" : "5d985be4-217c-472c-ae02-d6fca454662b",
    "created" : ISODate("2019-05-14T16:45:41.021Z"),
    "accessed" : ISODate("2019-05-14T17:18:59.118Z"),
    "interval" : "PT30M",
    "principal" : null,
    "expireAt" : ISODate("2019-05-14T17:48:59.118Z"),
    "attr" : BinData(0,"rO0ABXNyABFqYXZhLnV0aWwuSGFzaE1hcAUH2sHDFmDRAwACRgAKbG9hZEZhY3RvckkACXRocmVzaG9sZHhwP0AAAAAAAAx3CAAAABAAAAABdAAFY291bnRzcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAC3g=")
}

Oid is a UUID that will be Base64-encoded by the _DefaultCookieSerializere definido como um valor no cookieSESSION. Além disso, observe que o atributoattr contém o valor real do nosso contador.

8. Conclusão

Neste tutorial, exploramos Spring Session com MongoDB - uma ferramenta poderosa para gerenciar sessões HTTP em um sistema distribuído. Com este propósito em mente, pode ser muito útil emsolving the problem of replicating sessions across multiple instances da aplicação.

Como de costume, o código-fonte está disponívelover on GitHub.