Новое Распределяем каналы MAX по категориям и территориям. Читать новость

Ограничиваем чтение старых Java-объектов!



Если старый формат уже использует ObjectInputStream, входной поток нельзя считать доверенным. ObjectInputFilter ограничивает размер графа объектов и разрешает только классы, ожидаемые конкретным форматом.

Перечисляем допустимые типы явно:

private static final Set<Class<?>> ALLOWED =
    Set.of(LegacyRecord.class, String.class);{}


В список включаются тип корневой записи и типы её полей, которые действительно сериализуются. Широкие разрешения для всех классов пакета превращают allowlist в формальность.

Сначала отсекаем слишком большие графы:

private static boolean tooLarge(
        ObjectInputFilter.FilterInfo info) {
    return info.depth() > 10
        || info.references() > 500
        || info.streamBytes() > 1_000_000;
}{}


Лимит глубины защищает от чрезмерно вложенных структур, а число ссылок ограничивает количество объектов. Дополнительно можно ограничить общий размер потока через info.streamBytes().

Проверяем тип каждого объекта отдельно:

private static boolean allowed(Class<?> type) {
    return type == null || ALLOWED.contains(type);
}{}


Для служебных проверок фильтр может получить null вместо класса. Такой случай не означает, что неизвестный тип разрешён, поэтому решение о нём остаётся за статусом UNDECIDED.

Сначала отклоняем превышение лимитов и получаем тип:

private static ObjectInputFilter.Status filter(
        ObjectInputFilter.FilterInfo info) {
    if (tooLarge(info))
        return ObjectInputFilter.Status.REJECTED;
    Class<?> type = info.serialClass();{}


Затем разрешаем только перечисленные классы:

    if (type == null)
        return ObjectInputFilter.Status.UNDECIDED;
    return allowed(type)
        ? ObjectInputFilter.Status.ALLOWED
        : ObjectInputFilter.Status.REJECTED;{}


Эти проверки составляют тело фильтра. Превышение лимита отклоняется сразу, а неизвестный тип получает REJECTED, не проходя дальше по потоку.

Подключаем фильтр к потоку до десериализации:

input.setObjectInputFilter(MyFilters::filter);{}


Здесь MyFilters.filter объединяет проверки лимитов и типов из предыдущих шагов. Фильтр важно подключить до чтения, иначе объекты уже могут быть созданы.

После настройки получаем ожидаемый корневой объект:

LegacyRecord record = LegacyRecord.class
    .cast(input.readObject());{}


👉 Java Ready | практика
Просмотры: 252
Открыть в MAX Сообщить о неточности

Сообщить о неточности

Опишите, что нужно исправить. Если есть источник, добавьте ссылку.

Вы покидаете datool.ru

Ссылка ведёт на внешний сайт. datool.ru не отвечает за его содержимое — проверьте адрес, прежде чем вводить пароли или платёжные данные.

Переход через 10 с

Перейти