O padrão de proxy de serialização (recomendada pelo livro) ainda é uma solução válida e segura no Java, especialmente para classes com invariantes complexas ou que exigem imutabilidade real. No entanto, com as evoluções da linguagem e das práticas de desenvolvimento, há abordagens mais modernas e recomendadas para muitos cenários.
Abordagens mais modernas para segurança na serialização e desserialização
1- Evitar completamente a serialização nativa do Java (Serializable)
- O próprio criador do Java (Joshua Bloch) recomenda evitar Serializable devido aos riscos de segurança e complexidade.
- Em vez disso, é melhor utilizar formatos de serialização mais seguros, como JSON, XML ou Protobuf, que oferecem mais controle sobre o que está sendo serializado.
Alternativas:
- Usar Jackson (com.fasterxml.jackson.databind) para JSON.
- Utilizar Protocol Buffers (protobuf) / Apache Avro para uma serialização mais eficiente e segura.
2- Uso de classes imutáveis e transient
- Objetos imutáveis são naturalmente mais seguros para serialização.
Usar Classes Imutáveis Modernas
Substitua tipos mutáveis (ex.: Date, ArrayList) por classes imutáveis do java.time (LocalDate, Instant) ou coleções imutáveis (List.of(), Set.copyOf()).
Records (Java 16+):
public record Period(LocalDate start, LocalDate end) {
// Validação no construtor compacto
public Period {
if (end.isBefore(start)) throw new IllegalArgumentException();
}
}
Simplifica a criação de classes imutáveis e elimina a necessidade de cópias defensivas.
- Marcar campos sensíveis como transient impede que sejam serializados.
Exemplo:
public final class SecureData implements Serializable {
private static final long serialVersionUID = 1L;
private final String publicData;
private transient String sensitiveData; // Não será serializado
public SecureData(String publicData, String sensitiveData) {
this.publicData = publicData;
this.sensitiveData = sensitiveData;
}
}
3- ObjectInputFilter (Desde Java 9)
- Java 9 introduziu o ObjectInputFilter, que permite definir filtros de segurança para impedir ataques de desserialização de objetos inesperados ou perigosos.
Exemplo:
ObjectInputFilter filter = ObjectInputFilter.Config.createFilter(
"com.meusistema.SeguraClass;!*"
);
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("data.ser"));
ois.setObjectInputFilter(filter);
Benefício: Permite controlar quais classes podem ser desserializadas.
4- Biblioteca Kryo (Mais segura e rápida)
- Kryo é uma alternativa moderna e eficiente para serialização, sendo mais rápida e mais segura que a serialização padrão do Java.
Kryo kryo = new Kryo();
Output output = new Output(new FileOutputStream("data.bin"));
kryo.writeObject(output, myObject);
output.close();
Leitura:
https://medium.com/@prekshaan95/kryo-serialization-and-deserialization-in-java-9e6da25e2a76
Benefício: Melhor desempenho e segurança, usado em frameworks como Akka.
5- Serialização Customizada com writeObject() e readObject()
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
throw new InvalidObjectException("Desserialização não permitida!");
}
Benefício: Bloqueia ataques de desserialização.
6- Serialização com Frameworks Seguros
Spring Boot / Micronaut / Quarkus:
- Frameworks modernos evitam a serialização nativa do Java, preferindo JSON via REST APIs.
- Usam DTOs (Data Transfer Objects) imutáveis para transferência segura de dados.
7- Padrão de Serialização Baseada em Construtores
Em vez de depender de proxies, use construtores ou factories para reconstruir objetos após a desserialização:
public class Period implements Serializable {
private final LocalDate start;
private final LocalDate end;
// Construtor público com validação
public Period(LocalDate start, LocalDate end) {
if (end.isBefore(start)) throw new IllegalArgumentException();
this.start = start;
this.end = end;
}
private Object readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
ois.defaultReadObject();
return new Period(start, end); // Reconstrução segura
}
}
Quando o Proxy de Serialização Ainda é Útil?
- Cenários críticos: Sistemas financeiros, APIs de segurança, onde a validação rigorosa é essencial.
- Legado: Projetos que não podem migrar para formatos modernos (ex.: sistemas embarcados, aplicações empresariais antigas).
Comparativo: Proxy vs. Alternativas Modernas
Conclusão: Qual abordagem usar?
Se a segurança for crítica, evite Serializable e use JSON ou Protobuf. Se ainda precisar usar Serializable, aplique ObjectInputFilter e classes imutáveis.
Top comments (0)