setSerialFilterFactoryを使用したフィルタ・ファクトリの設定
メソッドObjectInputFilter.Config.setSerialFilterFactoryを呼び出してフィルタ・ファクトリを設定すると、ObjectInputStream
が構築されたとき、およびストリーム固有のフィルタがObjectInputStream
に設定されたときに、フィルタ・ファクトリのメソッドBinaryOperator<ObjectInputFilter>.apply(ObjectInputFilter t, ObjectInputFilter u)
が呼び出されます。パラメータt
は現在のフィルタで、u
はリクエストされたフィルタです。applyが最初に呼び出されたとき、t
はnullになります。JVM全体のフィルタが設定されている場合、applyが最初に呼び出されたとき、u
はJVM全体のフィルタになります。それ以外の場合、u
はnullになります。applyメソッド(自分で実装する必要がある)は、ストリームに使用されるフィルタを返します。applyが再度呼び出された場合、パラメータt
はこの返されたフィルタになります。メソッドObjectInputStream.setObjectInputFilter(ObjectInputFilter)を使用してフィルタを設定すると、パラメータu
がこのフィルタになります。
次の例では、apply
メソッドが呼び出されるたびにObjectInputFilterパラメータを出力する単純なフィルタ・ファクトリを実装し、これらのパラメータを1つの結合フィルタにマージしてから、このマージ済フィルタを返します。
public class SimpleFilterFactory {
static class MySimpleFilterFactory implements BinaryOperator<ObjectInputFilter> {
public ObjectInputFilter apply(
ObjectInputFilter curr, ObjectInputFilter next) {
System.out.println("Current filter: " + curr);
System.out.println("Requested filter: " + next);
return ObjectInputFilter.merge(next, curr);
}
}
private static byte[] createSimpleStream(Object obj) {
ByteArrayOutputStream boas = new ByteArrayOutputStream();
try (ObjectOutputStream ois = new ObjectOutputStream(boas)) {
ois.writeObject(obj);
return boas.toByteArray();
} catch (IOException ioe) {
ioe.printStackTrace();
}
throw new RuntimeException();
}
public static void main(String[] args) throws IOException {
// Set a filter factory
MySimpleFilterFactory contextFilterFactory = new MySimpleFilterFactory();
ObjectInputFilter.Config.setSerialFilterFactory(contextFilterFactory);
// Set a stream-specific filter
ObjectInputFilter filter1 =
ObjectInputFilter.Config.createFilter("example.*;java.base/*;!*");
ObjectInputFilter.Config.setSerialFilter(filter1);
// Create another filter
ObjectInputFilter intFilter = ObjectInputFilter.allowFilter(
cl -> cl.equals(Integer.class), ObjectInputFilter.Status.UNDECIDED);
// Create input stream
byte[] intByteStream = createSimpleStream(42);
InputStream is = new ByteArrayInputStream(intByteStream);
ObjectInputStream ois = new ObjectInputStream(is);
ois.setObjectInputFilter(intFilter);
try {
Object obj = ois.readObject();
System.out.println("Read obj: " + obj);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
この例では、次のような出力が表示されます(わかりやすくするために改行が追加されています):
Current filter: null
Requested filter: example.*;java.base/*;!*
Current filter: example.*;java.base/*;!*
Requested filter:
merge(
predicate(
SimpleFilterFactory$$Lambda$8/0x0000000800c00c60@76ed5528,
ifTrue: ALLOWED, ifFalse: UNDECIDED),
predicate(
SimpleFilterFactory$$Lambda$9/0x0000000800c01800@2c7b84de,
ifTrue: REJECTED, ifFalse: UNDECIDED))
Read obj: 42
apply
メソッドは2回呼び出されます。ObjectInputStream ois
が作成されたとき、およびメソッドsetObjectInputFilter
が呼び出されたときです。
ノート:
- フィルタをObjectInputStreamに設定できるのは1回のみです。それ以外の場合は、
IllegalStateException
がスローされます。 - 予期しないデシリアライズから保護するには、セキュリティ・エキスパートは、フィルタ・ファクトリがフィルタを選択して組み合せる方法を徹底的に確認します。