This tutorial shows you how to configure Spring Session to distribute your session using MySQL
Session management in multi-node applications presents multiple challenges. When the architecture includes a load balancer, client requests might be routed to different servers each time, and the HTTP session might be lost. In this tutorial, we will walk you through the configuration of session sharing in a multi-node Spring Boot application.
Prerequisites:
Session Persistence is a technique for sticking a client to a single server, using application layer information—like a cookie, for example. In this tutorial, we will implement session persistence with the help of HAProxy, a reliable, high performance, TCP/HTTP load balancer.
First, let’s create a web application with Okta authentication and run three nodes with HAProxy load balancing using Docker Compose.
Create a Maven project using the Spring Initializr’s API.
curl https://start.spring.io/starter.zip \
-d dependencies=web,okta \
-d groupId=com.okta.developer \
-d artifactId=webapp \
-d name="Web Application" \
-d description="Demo Web Application" \
-d packageName=com.okta.developer.webapp \
-d javaVersion=11 \
-o web-app.zip
Unzip the project:
unzip web-app.zip -d web-app
cd web-app
Run the Okta Maven Plugin to register a new account:
./mvnw com.okta:okta-maven-plugin:register
If you already have an Okta account registered, use login
instead of register
.
Then, configure your Spring application for authentication using Okta:
./mvnw com.okta:okta-maven-plugin:spring-boot
It will set up a new OIDC application for you and write your Okta settings to your src/main/resources/application.properties
file.
Create a GreetingController
at src/main/java/com/okta/developer/webapp/controller
:
package com.okta.developer.webapp.controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.oauth2.core.oidc.user.OidcUser;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.request.RequestContextHolder;
import java.net.InetAddress;
@Controller
public class GreetingController {
private static final Logger logger = LoggerFactory.getLogger(GreetingController.class);
@GetMapping(value = "/greeting")
@ResponseBody
public String getGreeting(@AuthenticationPrincipal OidcUser oidcUser) {
String serverUsed = "unknown";
try {
InetAddress host = InetAddress.getLocalHost();
serverUsed = host.getHostName();
} catch (Exception e){
logger.error("Could not get hostname", e);
}
String sessionId = RequestContextHolder.currentRequestAttributes().getSessionId();
logger.info("Request responded by " + serverUsed);
return "Hello " + oidcUser.getFullName() + ", your server is " + serverUsed + ", with sessionId " + sessionId;
}
}
Run the application with:
./mvnw spring-boot:run
#mysql #spring-boot #java #programming #developer