Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/redis/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Redis、SpringBoot和HttpSession:我应该加密会话数据吗?_Session_Redis_Spring Boot_Session Variables_Spring Session - Fatal编程技术网

Redis、SpringBoot和HttpSession:我应该加密会话数据吗?

Redis、SpringBoot和HttpSession:我应该加密会话数据吗?,session,redis,spring-boot,session-variables,spring-session,Session,Redis,Spring Boot,Session Variables,Spring Session,我正在使用Spring Boot 1.3.3构建一个web应用程序。我使用Redis处理会话 我将在HttpSession中设置一些“关键”数据,我想了解这将如何与Redis一起工作。是存储在服务器端的信息加上浏览器端的键,还是所有数据都在用户浏览器的cookie中 我想看看答案的文档参考,或者获得权威性的答案(例如,Pivotal dev)。创建者或redis提供的关于redis安全性的非常好的文章-读起来非常有趣。也请阅读评论 我很好奇的一件事是,您的“关键”数据是否必须存储在会话中?如果它

我正在使用Spring Boot 1.3.3构建一个web应用程序。我使用Redis处理会话

我将在
HttpSession
中设置一些“关键”数据,我想了解这将如何与Redis一起工作。是存储在服务器端的信息加上浏览器端的键,还是所有数据都在用户浏览器的cookie中


我想看看答案的文档参考,或者获得权威性的答案(例如,Pivotal dev)。

创建者或redis提供的关于redis安全性的非常好的文章-读起来非常有趣。也请阅读评论


我很好奇的一件事是,您的“关键”数据是否必须存储在会话中?如果它对性能不是非常关键,您可以将其保存在数据库中。我在产品中使用redis只是为了存储令牌和基本用户数据,我见过有人将大数据量作为会话数据转储,这很好,但我认为这不是一个好主意

在我看来,您应该避免在redis中加密数据,否则会造成性能开销。因此,您可能希望将redis节点放在一个受保护的区域(内部),在该区域中,只允许来自应用程序的流量到达。如果不可能,则可以使用IPSec/Stunnel保护通信


顺便说一句,将会话数据存储为HTTPSession属性将比从Redis检索它更快。但我相信你会选择redis,可能是因为数据量太大。

虽然我同意这里其他答案的大部分说法,但其他答案都没有回答这个问题。 我假设您正在SpringBoot中使用SpringSession和Redis

为了使用SpringSession,您可能(直接或间接)配置了一个servlet过滤器,该过滤器扩展了
SessionRepositoryFilter

SessionRepositoryFilter使用
SessionRepository
。由于您使用的是Redis,因此您的配置很可能使用了
RedisOperationsSessionRepository

RedisOperationsSessionRepository
实现了您可能猜到的
SessionRepository
,并最终负责基于密钥(在您的情况下,密钥可能存储为用户浏览器上的cookie)获取、存储和删除会话

默认情况下,
RedisOperationSessionRepository
使用实现了
RedisSerializer
JdkSerializationRedisSerializer
,在将所述数据交给Redis之前对会话数据进行序列化

根据的文档,可以通过其
setDefaultSerializer
方法设置
RedisOperationsSessionRepository
将使用的默认序列化程序

理论上,您可以扩展
JdkSerializationRedisSerializer
,并在那里执行加密和解密
JdkSerializationRedisSerializer
如下所示:

public class JdkSerializationRedisSerializer implements RedisSerializer<Object> {

    private Converter<Object, byte[]> serializer = new SerializingConverter();
    private Converter<byte[], Object> deserializer = new DeserializingConverter();

    public Object deserialize(byte[] bytes) {
        if (SerializationUtils.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 SerializationUtils.EMPTY_ARRAY;
        }
        try {
            return serializer.convert(object);
        } catch (Exception ex) {
            throw new SerializationException("Cannot serialize", ex);
        }
    }
}
其中EncrpytionUtils可能看起来像:

public class CrypticRedisSerializer extends JdkSerializationRedisSerializer {

    @Override
    public Object deserialize(byte[] bytes) {
        byte[] decrpyted;
        try {
            decrpyted = EncryptionUtils.decrypt(bytes);
            return super.deserialize(decrpyted);
        } catch (NoSuchPaddingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (GeneralSecurityException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        // handle expections or allow to propagate, your choice!
        return null;
    }

    @Override
    public byte[] serialize(Object object) {
        byte[] bytes = super.serialize(object);

        try {
            return EncryptionUtils.encrypt(bytes);
        } catch (NoSuchPaddingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (GeneralSecurityException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        // handle expections or allow to propagate, your choice!
        return null;
    }

}
public class EncryptionUtils {
    private static SecretKeySpec skeySpec;

    static {    
        try {           
            ClassPathResource res = new ClassPathResource("key.key");
            if(res != null){
                File file = res.getFile();
                FileInputStream input = new FileInputStream(file);
                byte[] in = new byte[(int)file.length()];
                input.read(in);
                skeySpec = new SecretKeySpec(in, "AES");
                input.close();
            }
        }catch (FileNotFoundException e) {
            e.printStackTrace();
        }catch (IOException e) {
            e.printStackTrace();
        }
    }


    public static byte[] encrypt(byte[] input) 
            throws GeneralSecurityException, NoSuchPaddingException{
           Cipher cipher = Cipher.getInstance("AES");

           cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
           return cipher.doFinal(input);

    }


    public static byte[] decrypt(byte[] input) throws GeneralSecurityException, NoSuchPaddingException{
        Cipher cipher = Cipher.getInstance("AES");
        cipher.init(Cipher.DECRYPT_MODE, skeySpec);
        return cipher.doFinal(input);
    }

}
要实现这一点,您需要做的就是确保将自定义序列化程序设置为
RedisOperationSessionRepository
用户的默认序列化程序

请注意:

  • 我没有测试上面的代码
  • 我并不是说上面的代码是一个理想的解决方案或解决方案,而是简单地演示了一种将encrpytion引入到使用Redis的SpringSession中的机制
  • 显然,您可以使用任何想要的双向加密算法。EncrpytionUtils只是一个例子
  • 这将影响性能。多少钱?没有测试很难说。请注意,这会对性能产生一些影响
  • 如果您真的担心加密发送到Redis的会话数据,那么我强烈建议您也确保服务器的安全。确保只有需要访问Redis服务器的服务器才能访问。把它放在防火墙后面。如果您使用的是AWS之类的云服务,请将您的Redis服务器置于VPN中,并置于私有子网内
  • 然而,正如他们所建议的,您可以使用来确保您的连接是加密的 文件和结帐参考:


  • 我想存储一些“经典”的东西,比如代币、购物车、面向未注册用户的东西?如果是的话,我可以回答这个问题。让我知道。很好的回答!我唯一需要解决的问题是如何确保在使用SpringBoot和SpringSessionDataRedis时始终应用自定义序列化程序,后者在幕后神奇地配置了大部分相关组件。我最终得到了一个配置类,该类扩展了RedisHttpSessionConfiguration,并在PostConstruct方法中应用CrypticRedisSerializer实例。现在双向都可以了,谢谢你的样品。