Sessão de primavera com MongoDB
1. Visão geral
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.