import java.io.Serializable;
import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ObjectInputStream;
public class DemoSerialization {
enum ROLE {
DIRECTOR, EMPLOYEE;
}
private static final class Salary implements Serializable {
private int salary;
private static final long serialVersionUID = 1L;
public Salary(ROLE role) {
switch (role) {
case DIRECTOR:
salary = 1000000;
break;
case EMPLOYEE:
salary = 80000;
break;
default:
salary = 0;
}
}
public final int giveSalaryAmount() {
return salary;
}
}
public static void main(String[] args) throws java.io.IOException, java.lang.ClassNotFoundException {
Salary salaryDirector = new Salary(ROLE.DIRECTOR);
Salary salaryEmployee = new Salary(ROLE.EMPLOYEE);
System.out.println("Payement: ");
// 1
System.out.println("- director will get " + salaryDirector.giveSalaryAmount());
System.out.println("- employee will get " + salaryEmployee.giveSalaryAmount());
}
}
Cette petite classe, bien que peu intéressante dans son contenu, va néanmoins afficher le salaire du directeur et le salaire de l'employé.
La classe est "sécurisée" par le constructeur, qui ne prend pas un salaire mais un type d'employé. La classe est finale, le salaire également.
Au point 1, on peut imaginer que salaryDirectory, salaryEmployee est sérialisé: Spring remoting, mise en session, etc... est-ce que ça pose un problème ?
ça peut poser un problème si la classe a subit des modifications et qu'un client n'a pas la même version, ou qu'un pirate vient s'integrer dans la connexion. Pour continuer l'exemple, insérons ceci au point (1), simulant un appel remote par exemple ou dans tous les cas une désérialization:
byte[] bytesH = new byte[]{-84,-19,0,5,115,114,0,24,68,101,109,111,83,101,114,105,97,108,105,122,97,116,105,111,110,36,83,97,108,97,114,121,0,0,0,0,0,0,0,1,2,0,1,73,0,6,115,97,108,97,114,121,120,112,0,15,66,64};
// Deserialization
ByteArrayInputStream bais = new ByteArrayInputStream(bytesH);
ObjectInputStream in = new ObjectInputStream(bais);
salaryEmployee = (Salary)in.readObject();
Que se passe-t'il ? je connais un employé qui va recevoir beaucoup d'argent...
Ce petit exemple montre qu'il est important de définir un serialVersionUID différent pour chaque changement d'interface, ou de laisser la JVM le générer d'après la signature de la classe, des champs et méthodes. Mais plus jamais nous ne devrions tolérer de serialVersionUID=1l, généré par défaut, sous peine d'avoir un comportement étrange entre des versions différentes !