【问题标题】:Spring session unable save session to RedisSpring session 无法将 session 保存到 Redis
【发布时间】:2017-11-02 08:44:38
【问题描述】:

我有一个与 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] 在 org.springframework.core.serializer.support.SerializingConverter.convert(SerializingConverter.java:35) ~[spring-core-4.3.2.RELEASE.jar:4.3.2.RELEASE] 在 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));
  }
}

怎么了?

我很困惑

感谢您的帮助。

【问题讨论】:

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


    【解决方案1】:

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

    【讨论】:

      猜你喜欢
      • 2019-02-12
      • 2016-04-23
      • 2021-09-13
      • 2017-04-02
      • 2019-10-15
      • 2018-12-16
      • 2016-12-09
      • 2018-08-28
      • 2015-09-08
      相关资源
      最近更新 更多