3

When you use spring-session-jdbc, the sessions are serialized in DB as bytes, which means you have to drop all sessions every time you upgrade Spring to a version with incompatible Session.serialVersionUUID.

I wanted to store the session in JSON format but after some googling it seems like nobody has ever done this.

This is weird when you consider that storing sessions in Redis using JSON is common practice.

Why isn't there a standard way to store sessions in JDBC in JSON format? And how could this be achieved?

asked Feb 8, 2019 at 14:20

2 Answers 2

1

The main problem with JSON is object types: you can easily serialize objects as JSON, but when it comes to deserializing - you can never know what type of object this JSON respresents.

I've faced with kind of same problem. But it was enough for me to parse only the part of JSON data, which comes to session from external source. My solution was to create two new implementations of org.springframework.core.convert.converter.Converter interface - one for serializing (Object to byte[]) and one for deserializing (byte[] to Object), and then register them as converters for Spring. This converters are used by org.springframework.session.jdbc.JdbcOperationsSessionRepository to store/read session attributes bytes. You can create your implementations like so (used Jackson library to work with JSON):

JsonSerializingConverter

@Component
public class JsonSerializingConverter implements Converter<Object, byte[]> {
 @Override
 public byte[] convert(Object source) {
 ObjectMapper objectMapper = new ObjectMapper();
 try {
 return objectMapper.writeValueAsBytes(source);
 } catch (IOException e) {
 e.printStackTrace();
 }
 return null;
 }
}

JsonDeserializingConverter

@Component
public class JsonDeserializingConverter implements Converter<byte[], Object> {
 @Override
 public Object convert(byte[] source) {
 ObjectMapper objectMapper = new ObjectMapper();
 try {
 return objectMapper.readValue(source, Object.class);
 } catch (IOException e) {
 e.printStackTrace();
 }
 return null;
 }
}

Next you should register them:

@Configuration
public class ConversionServiceConfiguration
{
 @Bean
 public ConversionServiceFactoryBean conversionService()
 {
 ConversionServiceFactoryBean bean = new ConversionServiceFactoryBean();
 bean.setConverters(getConverters());
 return bean;
 }
 private Set<Converter> getConverters()
 {
 Set<Converter> converters = new HashSet<>();
 converters.add(new JsonDeserializingConverter());
 converters.add(new JsonSerializingConverter());
 return converters;
 }
}

It will work fine unless you don't need to bind JSON data with object (for example CsrfToken object). In such case, you probably can annotate your JSON string with target type on serializing step, and deserialize into that type on deserialization step. Hope this might help.

answered Apr 2, 2019 at 9:33
Sign up to request clarification or add additional context in comments.

Comments

1

I'm pretty late to this answer, but Spring Security 6.3 now keeps serialization for its classes between minor versions, see the blog post.

In addition to that, I just pushed some changes to improve the documentation around Spring Session JDBC and those changes include how to save session attributes as JSON, see https://docs.spring.io/spring-session/reference/configuration/jdbc.html#session-attributes-as-json

answered Mar 1, 2024 at 19:10

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.