직렬화

직렬화란?

직렬화의 문제

readObject : 보이지 않는 생성자

readObject메서드를 호출하면 객체 그래프가 역직렬화 되기 때문에, 클래스안의 거의 모든 타입의 객체를 만들어 낼 수 있는 마법같은 생성자이다.

하지만 유효성 검증이 어려워 보안에 문제가 있으며, 보이지 않는 생성자라고 불린다.

일반 생성자

//양수를 저장하는 클래스
public class PositiveNumber implements Serializable {
	public final int value;
	
	public PositiveNumber(final int value) {
		this.value = value;
		//양수 validation검증 필요
		if (this.value < 0) {
			throw new RuntimeException();
		}
	}
}

validation 로직을 적용하여, 객체가 생성될때 유효성을 검증할 수 있다.

readObject


//PositiveNumber 객체를 직렬화하는 함수 
private byte[] getSerialzedObject(int value) throws IOException{
	byte[] serializedObject;
	
	try(ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
			ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream)){
		
		PositivieNumber positiveNumber = new PositiveNumber(value);
		ojbectOutputStream.writeObject(positiveNumber);
		serializedObject = byteArrayOutputStream.toByteArray();
	}

}

byte[] serializedObject = getSerialzedObject(1); //양수로 정상 초기화 + 직렬화 

//악의적인 사용자가 해당 값을 변경할 경우 
serializedObject[43] = -1;
serializedObject[44] = -1;
serializedObject[45] = -1;
serializedObject[46] = -1;

//역직렬화
try(ByteArrayInputStream byteArrayInputStream = new ByteArrayInpuutStream();
			ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream)){
		
		PositivieNumber positiveNumber = (PositiveNumber) objectInputStream.readObject();
		objectOutputStream.writeObject(positiveNumber);

		positiveNumber.value; // -1 이 나옴		
}

readObject가 validation로직을 포함하지 않기 때문에, 유효성을 만족하지 않는 객체의 생성을 막을 수 없음