微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

任何服务器、框架或 J2EE 本身仍然在 Java 中的任何地方使用序列化吗? “连载在 1997 年是一个可怕的错误”

如何解决任何服务器、框架或 J2EE 本身仍然在 Java 中的任何地方使用序列化吗? “连载在 1997 年是一个可怕的错误”

一个 Sonar rule 称为 “Serializable”类中的字段应该是瞬态的或可序列化的。当您向类中添加不可序列化的字段时,它就会出现。规则规定:

例如,在负载情况下,大多数 J2EE 应用程序框架会将对象刷新到磁盘,而据称具有非暂时性、不可序列化数据成员的可序列化对象可能会导致程序崩溃,并为攻击者打开大门。

这对我来说听起来已经过时了。在Effective Java 3rd Edition 中指出,在开发新软件时,序列化并不相关。还有,Removing Serialization from Java Is a 'Long-Term Goal' at Oracle。 Java 首席架构师 Mark Reinhold 本人表示

“连载在 1997 年是一个可怕的错误。”

这里已经问过这个问题,如果 Spring 框架可以刷新对象:

所以我问这个问题: 是否有任何现代应用服务器、框架或 J2EE 实现本身(尤其是与 CDI、EJB、JPA 交互的 Java 组件)在重负载下将对象刷新到磁盘?

或者这个说法已经过时了?

解决方法

TL;DR

如果您没有实现可分发的 Web 应用程序,您没有启用会话持久性,并且您只使用内存缓存,那么您可能无需在任何地方使用 Serializable。

说明

对于会话复制,Java Serialization 仍然是最新的 Servlet 规范所必须的:https://jakarta.ee/specifications/servlet/5.0/jakarta-servlet-spec-5.0.html#distributed-environments

一个常见的用例是,如果您在负载均衡器后面有多个服务器,并且您在一个服务器上登录,您将获得一个 JSESSIONID cookie。如果负载均衡器为下一个请求将您发送到不同的服务器,您的登录属性和其他会话范围的属性将被序列化并复制到新服务器上,因此您的 JSESSIONID 在那里仍然有效。

另一个需要序列化会话范围属性的用例是应用程序服务器决定将会话交换到磁盘时。例如Tomcat 8,这可以配置为在内存中保留太多会话时激活,或者在服务器重新启动时激活,并且您希望保持会话活动。看 https://tomcat.apache.org/tomcat-9.0-doc/config/manager.html

对于这些类型的用例,每个 Servlet-5.0 兼容的应用服务器都必须默认支持 Http Sessions 中的 Serializable 对象。

对于某些服务器,这可以通过使用例如调整或覆盖Jackson-JSON 序列化或类似的东西。见例如How to use jackson instead of JdkSerializationRedisSerializer in spring

另一个常见的用例是缓存。这用于保持对象尽可能快地访问,理想情况下在内存中,但可能暂时卸载到磁盘或外部缓存服务器。 有一个标准 API (JSR-107) 明确选择不需要 Serializable 对象,但大多数实现仍然默认使用 java Serialization 作为卸载部分。

您可以再次调整这些以支持其他序列化机制,例如对于 ehcache:https://www.ehcache.org/documentation/3.8/serializers-copiers.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。