Item 90: Pense em usar proxies de serialização em vez de instâncias serializadas

Atenção: Com as evoluções do Java e práticas modernas, existem alternativas mais seguras e eficientes para lidar com serialização/desserialização. Mas como estamos estudando o livro vamos considerar para aprender. VER NO TÓPICO FINAL SOBRE SERIALIZAÇÃO Resumo do Item 90: Use Proxies de Serialização em vez de Instâncias Serializadas Problemas da Serialização Direta Riscos de segurança e bugs: Permite criar objetos sem passar por construtores normais. Violação de invariantes: Desserialização pode gerar instâncias inválidas. Ataques maliciosos: Streams de bytes manipuladas podem explorar vulnerabilidades. O que é o Padrão de Proxy de Serialização? Objetivo: Substituir a serialização nativa por uma abordagem segura e controlada. Funcionamento: Cria uma classe proxy aninhada (serializável) que encapsula o estado da classe principal. Garante que apenas o proxy é serializado/desserializado, não a classe original. Implementação do Proxy de Serialização Criar a classe proxy: Classe estática privada, serializável, com campos idênticos à classe principal. Construtor recebe a instância original e copia seus dados. private static class SerializationProxy implements Serializable { private final Date start; private final Date end; SerializationProxy(Period p) { this.start = p.start; this.end = p.end; } } Método writeReplace na classe principal: Substitui a instância original pelo proxy durante a serialização. private Object writeReplace() { return new SerializationProxy(this); } Bloquear desserialização direta: Adicionar readObject que lança exceção para evitar bypass do proxy. private void readObject(ObjectInputStream ois) throws InvalidObjectException { throw new InvalidObjectException("Use o proxy!"); } Método readResolve no proxy: Converte o proxy de volta em uma instância válida da classe principal. private Object readResolve() { return new Period(start, end); // Usa o construtor público } Vantagens do Padrão Segurança reforçada: Elimina riscos de streams maliciosas e exposição de campos privados. Preserva imutabilidade: Campos final são mantidos sem restrições. Flexibilidade: Permite alterar a implementação interna da classe sem quebrar compatibilidade (ex.: EnumSet). Simplicidade: Mais fácil de validar do que cópias defensivas. Limitações Classes extensíveis: Não funciona bem se a classe pode ser herdada por usuários (viola encapsulamento). Grafos circulares: Pode causar ClassCastException em objetos com referências cíclicas. Desempenho: ~14% mais lento que serialização padrão (trade-off aceitável para segurança). Conclusão Use proxies de serialização sempre que: A classe tem invariantes complexas. A segurança é crítica (ex.: dados sensíveis). Quer evitar códigos de validação/cópia defensiva manuais. Priorize este padrão sobre readObject/writeObject customizados para garantir robustez e imutabilidade real. Chave: O proxy assegura que a desserialização sempre passa pelo construtor público, validando invariantes e bloqueando ataques! Exemplos do Livro:

Feb 13, 2025 - 01:30
 0
Item 90: Pense em usar proxies de serialização em vez de instâncias serializadas

Atenção: Com as evoluções do Java e práticas modernas, existem alternativas mais seguras e eficientes para lidar com serialização/desserialização. Mas como estamos estudando o livro vamos considerar para aprender. VER NO TÓPICO FINAL SOBRE SERIALIZAÇÃO

Resumo do Item 90: Use Proxies de Serialização em vez de Instâncias Serializadas

Problemas da Serialização Direta
Riscos de segurança e bugs:

  • Permite criar objetos sem passar por construtores normais.
  • Violação de invariantes: Desserialização pode gerar instâncias inválidas.
  • Ataques maliciosos: Streams de bytes manipuladas podem explorar vulnerabilidades.

O que é o Padrão de Proxy de Serialização?
Objetivo: Substituir a serialização nativa por uma abordagem segura e controlada.

Funcionamento:

  • Cria uma classe proxy aninhada (serializável) que encapsula o estado da classe principal.
  • Garante que apenas o proxy é serializado/desserializado, não a classe original.

Implementação do Proxy de Serialização

Criar a classe proxy:

  • Classe estática privada, serializável, com campos idênticos à classe principal.
  • Construtor recebe a instância original e copia seus dados.
private static class SerializationProxy implements Serializable {
    private final Date start;
    private final Date end;

    SerializationProxy(Period p) {
        this.start = p.start;
        this.end = p.end;
    }
}

Método writeReplace na classe principal:
Substitui a instância original pelo proxy durante a serialização.

private Object writeReplace() {
    return new SerializationProxy(this);
}

Bloquear desserialização direta:
Adicionar readObject que lança exceção para evitar bypass do proxy.

private void readObject(ObjectInputStream ois) throws InvalidObjectException {
    throw new InvalidObjectException("Use o proxy!");
}

Método readResolve no proxy:
Converte o proxy de volta em uma instância válida da classe principal.

private Object readResolve() {
    return new Period(start, end); // Usa o construtor público
}

Vantagens do Padrão

Segurança reforçada:

  • Elimina riscos de streams maliciosas e exposição de campos privados.
  • Preserva imutabilidade: Campos final são mantidos sem restrições.

Flexibilidade:

  • Permite alterar a implementação interna da classe sem quebrar compatibilidade (ex.: EnumSet).
  • Simplicidade: Mais fácil de validar do que cópias defensivas.

Limitações

  • Classes extensíveis: Não funciona bem se a classe pode ser herdada por usuários (viola encapsulamento).
  • Grafos circulares: Pode causar ClassCastException em objetos com referências cíclicas.
  • Desempenho: ~14% mais lento que serialização padrão (trade-off aceitável para segurança).

Conclusão

  • Use proxies de serialização sempre que:
  • A classe tem invariantes complexas.
  • A segurança é crítica (ex.: dados sensíveis).
  • Quer evitar códigos de validação/cópia defensiva manuais.
  • Priorize este padrão sobre readObject/writeObject customizados para garantir robustez e imutabilidade real.

Chave: O proxy assegura que a desserialização sempre passa pelo construtor público, validando invariantes e bloqueando ataques!

Exemplos do Livro:

Image description

Image description

Image description

Image description

Image description