Spring会话无法将会话保存到Redis

时间:2017-06-01 09:20:53

标签: spring spring-boot spring-security spring-session

我有一个与spring security集成的应用程序。我将此应用程序分离为两个应用程序,因此我希望使用Redis配置spring会话,以便在这两个应用程序之间进行集中身份验证。我已经配置了Redis但是当我想登录时,会引发以下异常:

  

引起:   org.springframework.core.serializer.support.SerializationFailedException:   无法使用DefaultSerializer序列化对象;嵌套异常   是java.io.NotSerializableException:   org.springframework.dao.support.PersistenceExceptionTranslationInterceptor     在   org.springframework.core.serializer.support.SerializingConverter.convert(SerializingConverter.java:68)   〜[spring-core-4.3.2.RELEASE.jar:4.3.2.RELEASE] at   org.springframework.core.serializer.support.SerializingConverter.convert(SerializingConverter.java:35)   〜[spring-core-4.3.2.RELEASE.jar:4.3.2.RELEASE] at   org.springframework.data.redis.serializer.JdkSerializationRedisSerializer.serialize(JdkSerializationRedisSerializer.java:90)   〜[spring-data-redis-1.7.2.RELEASE.jar:na] ... 35个常见帧   省略   引起:java.io.NotSerializableException:org.springframework.dao.support.PersistenceExceptionTranslationInterceptor       在java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1184)〜[na:1.8.0_111]       在java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548)〜[na:1.8.0_111]

RedisConfig:

@Configuration
@EnableRedisHttpSession
public class RedisConfig implements BeanClassLoaderAware {

    private ClassLoader loader;

    @Bean
    @Primary
    public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory cf) {
        RedisTemplate<String, String> redisTemplate = new RedisTemplate<String, String>();
        redisTemplate.setConnectionFactory(cf);
        redisTemplate.setKeySerializer(redisTemplate.getStringSerializer());
        redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer(Object.class));
        return redisTemplate;
    }

    @Bean
    public CookieSerializer cookieSerializer() {
        DefaultCookieSerializer serializer = new DefaultCookieSerializer();
        serializer.setCookieName("JSESSIONID"); // <1>
        serializer.setCookiePath("/"); // <2>
        serializer.setDomainNamePattern("^.+?\\.(\\w+\\.[a-z]+)$"); // <3>
        return serializer;
    }

    @Bean
    public HttpSessionStrategy httpSessionStrategy() {
        return new HeaderHttpSessionStrategy();
    }

    @Bean
    public LettuceConnectionFactory connectionFactory() {
        return new LettuceConnectionFactory();
    }

    ObjectMapper objectMapper() {
        ObjectMapper mapper = new ObjectMapper();
        mapper.registerModules(SecurityJackson2Modules.getModules(this.loader));
        return mapper;
    }

    public void setBeanClassLoader(ClassLoader classLoader) {
        this.loader = classLoader;
    }
}

和这个配置:

public class SafeDeserializationRepository<S extends ExpiringSession> implements SessionRepository<S> {

    private final SessionRepository<S> delegate;
    private final RedisTemplate<Object, Object> redisTemplate;

    private static final String BOUNDED_HASH_KEY_PREFIX = "spring:session:sessions:";
    // private static final Logger logger =
    // getLogger(SafeDeserializationRepository.class);

    public SafeDeserializationRepository(SessionRepository<S> delegate, RedisTemplate<Object, Object> redisTemplate) {
        this.delegate = delegate;
        this.redisTemplate = redisTemplate;
    }

    @Override
    public S createSession() {
        return delegate.createSession();
    }

    @Override
    public void save(S session) {
        delegate.save(session);
    }

    @Override
    public S getSession(String id) {
        try {
            return delegate.getSession(id);
        } catch (SerializationException e) {
            // logger.info("Deleting non-deserializable session with key {}",
            // id);
            redisTemplate.delete(BOUNDED_HASH_KEY_PREFIX + id);
            return null;
        }
    }

    @Override
    public void delete(String id) {
        delegate.delete(id);
    }
}

和RedisSessionConfig:

@Configuration
public class RedisSessionConfig extends RedisHttpSessionConfiguration {
  @Autowired
  RedisTemplate<Object, Object> redisTemplate;

  @Bean
  @Override
  public <S extends ExpiringSession> SessionRepositoryFilter<? extends ExpiringSession> springSessionRepositoryFilter(SessionRepository<S> sessionRepository) {
    return super.springSessionRepositoryFilter(new SafeDeserializationRepository<>(sessionRepository, redisTemplate));
  }
}

有什么问题?

我很困惑

感谢您的帮助。

1 个答案:

答案 0 :(得分:0)

几周前我遇到了类似的问题。请检查课程。您可以将java的implements Serializable用于这些类。当类不是Serializable时遇到问题。另请查看Jackson注释,以便您可以选择如何序列化对象。