Spring Boot with Session/Redis Serialization Error with Bad Active Directory Ldap Credentials

前端 未结 3 1554
醉酒成梦
醉酒成梦 2020-12-11 18:40

Hi I am new to Spring and Java, I am trying to implement a Gateway authentication server as described in this tutorial https://spring.io/guides/tutorials/spring-security-and

相关标签:
3条回答
  • 2020-12-11 19:13

    I figured out a solution to this problem. I am open to any suggestions to improve the answer.

    The solution is not complete as I need to look specifically for the com.sun.jndi.ldap.LdapCtx type when serialization fails so I can deal with that specific case and throw the SerializationException in all others. But I thought the general idea might be useful to anyone who is blocked on this.

    Now when invalid credentials are used (eg Bad Username or Incorrect Password) the application returns to the log in page rather than blowing up :)

    I added some RedisConfiguration to replace the RedisTemplate Spring Session is using.

    import com.gateway.utils.LdapFailAwareRedisObjectSerializer;
    
    @Configuration
    public class RedisConfiguration {
    
      @Primary
      @Bean
      public RedisTemplate<String,ExpiringSession> redisTemplate(RedisConnectionFactory connectionFactory) {
        RedisTemplate<String, ExpiringSession> template = new RedisTemplate<String, ExpiringSession>();
    
        template.setKeySerializer(new StringRedisSerializer());
        template.setHashKeySerializer(new StringRedisSerializer());
        template.setHashValueSerializer(new LdapFailAwareRedisObjectSerializer());
    
        template.setConnectionFactory(connectionFactory);
        return template;
      }
    }
    

    Here is my implementation of RedisSerializer<Object> (LdapFailAwareRedisObjectSerializer which is got from here)

    public class LdapFailAwareRedisObjectSerializer implements RedisSerializer<Object> {
    
      private Converter<Object, byte[]> serializer = new SerializingConverter();
      private Converter<byte[], Object> deserializer = new DeserializingConverter();
    
      static final byte[] EMPTY_ARRAY = new byte[0];
    
      public Object deserialize(byte[] bytes) {
        if (isEmpty(bytes)) {
          return null;
        }
    
        try {
          return deserializer.convert(bytes);
        } catch (Exception ex) {
          throw new SerializationException("Cannot deserialize", ex);
        }
      }
    
      public byte[] serialize(Object object) {
        if (object == null) {
          return EMPTY_ARRAY;
        }
    
        try {
          return serializer.convert(object);
        } catch (Exception ex) {
          return EMPTY_ARRAY;
          //TODO add logic here to only return EMPTY_ARRAY for known conditions
          // else throw the SerializationException
          // throw new SerializationException("Cannot serialize", ex);
        }
      }
    
      private boolean isEmpty(byte[] data) {
        return (data == null || data.length == 0);
      }
    }
    
    0 讨论(0)
  • 2020-12-11 19:20

    This just worked fine for me after using classes of org.springframework.core.serializer.support.DeserializingConverter and org.springframework.core.serializer.support.SerializingConverter

    /**
     * @author Meron Abraha 12/18/17
     */
    
    public class CustomRedisSerializer implements RedisSerializer<Object> {
    
    private Converter<Object, byte[]> serializer = new SerializingConverter();
    private Converter<byte[], Object> deserializer = new DeserializingConverter();
    
    static final byte[] EMPTY_ARRAY = new byte[0];
    
    public Object deserialize(byte[] bytes) {
        if (isEmpty(bytes)) {
            return null;
        }
    
        try {
            return deserializer.convert(bytes);
        } catch (Exception ex) {
            throw new SerializationException("Cannot deserialize", ex);
        }
    }
    
    public byte[] serialize(Object object) {
        if (object == null) {
            return EMPTY_ARRAY;
        }
    
        try {
            return serializer.convert(object);
        } catch (Exception ex) {
            return EMPTY_ARRAY;
    
        }
    }
    
    private boolean isEmpty(byte[] data) {
        return (data == null || data.length == 0);
    }
    }
    
    0 讨论(0)
  • 2020-12-11 19:25

    The Java object to be cached must implement the serializable interface, because spring will serialize the object and store it in redis.

    e.g. public class Store implement Serializable

    The short story here is ensure you implement the serializable interface on your class.

    I hope this help. Good luck.

    0 讨论(0)
提交回复
热议问题