• Serializable을 구현하기로 결정한 순간 언어의 정상 메커니즘인 생성자 이외의 방법으로 인스턴스를 생성할 수 있게 된다.
  • 직렬화 프록시 패턴을 사용하면 보안과 버그의 위협을 줄일 수 있다.

 

 

직렬화 프록시, serialization proxy pattern

  • 바깥 클래스의 논리적 상태를 정밀하게 표현하는 중첩 클래스를 설계해 private static으로 선언
    • 여기서 중첩 클래스가 바깥 클래스의 직렬화 프록시이다.
    • 중첩 클래스의 생성자는 단 하나여야하고 바깥 클래스를 매개변수로 받아야 함
    • 이 생성자는 단순히 인수로 넘어온 인스턴스의 데이터를 복사함
// Period 클래스용 직렬화 프록시

private static class SerializationProxy implements Serializable {
    private final Date start;
    private final Date end;

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

    private static final long serialVersionUID = 
                    23409824382341829L; // 아무 값이나 상관 없음
}
// 바깥 클래스에 writePlace 메소드 추가
// 직렬화 프록시 패턴용 writeReplace 메소드

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

/* 이 메소드가 바깥 클래스 인스턴스 대신
* SerilizationProxy의 인스턴스를 반환하는 역할을 함
/
  • writePlace 덕분에 직렬화 시스템은 결코 바깥 클래스의 직렬화된 인스턴스를 생성할 수 없음
  • readObject 메소드를 다음과 같이 설계해 공격도 방어할 수 있다
private void readObject(ObjectInputStream stream)
    throws InvalidObjectException {
    throws new InvalidObjectException("프록시가 필요합니다.");
}
  • readResolve 메소드는공개된 API만을 사용해 바깥 클래스의 인스턴스를 생성한다.

 

 

직렬화 프록시의 한계

  • 클라이언트가 멋대로 확장할 수 있는 클래스에는 적용할 수 없다.
  • 객체 그래프에 순환이 있는 클래스에도 적용할 수 없다.
  • 직렬화 프록시 패턴이 주는 강력함과 안전성에도 대가는 따르다 - 속도가 느려진다.

+ Recent posts