JAXB unmarshal: неожиданный элемент - PullRequest
0 голосов
/ 14 декабря 2018

Фон :

Я использую JAXB для демонтажа XML в объекты Java.Первоначально я использовал JAXB для выполнения демаршала.Затем был выполнен статический анализ кода, и была поднята проблема высокой критичности для инъекции внешнего объекта XML.После небольшого исследования я нашел предложение (https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Prevention_Cheat_Sheet#JAXB_Unmarshaller) использовать синтаксический анализатор, настроенный для предотвращения синтаксического анализа внешних объектов. Был приведен пример того, что нужно сделать:

//Disable XXE
SAXParserFactory spf = SAXParserFactory.newInstance();
spf.setFeature("http://xml.org/sax/features/external-general-entities", false);
spf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
spf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);

//Do unmarshall operation
Source xmlSource = new SAXSource(spf.newSAXParser().getXMLReader(), new InputSource(new StringReader(xml)));
JAXBContext jc = JAXBContext.newInstance(Object.class);
Unmarshaller um = jc.createUnmarshaller();
um.unmarshal(xmlSource);

У меня нетсделал это точно так, как показано, но я думаю, что я сделал то же самое в действительности:

XMLReader reader = getXMLReader();

if (reader == null) {
  logger.warn("Unable to create XML reader");
  return;
}

JAXBContext context = JAXBContext.newInstance(messageClass);
Unmarshaller unmarshaller = context.createUnmarshaller();

for (File file : files) {
  try {
    InputSource source = new InputSource(new FileReader(file));
    Source xmlSource = new SAXSource(reader, source);
    JAXBElement<? extends BaseType> object =
        (JAXBElement<? extends BaseType>) unmarshaller.unmarshal(xmlSource);
    messages.add(object.getValue());
  } catch (FileNotFoundException e) {
    logger.error("Exception", e);
  }
}

...

private XMLReader getXMLReader() {
    SAXParserFactory factory = SAXParserFactory.newInstance();

    try {
      factory.setFeature("http://xml.org/sax/features/external-general-entities", false);
      factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
      factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
    } catch (SAXNotRecognizedException | SAXNotSupportedException
        | ParserConfigurationException e) {
      logger.error("Exception", e);
    }

    XMLReader reader = null;

    try {
      reader = factory.newSAXParser().getXMLReader();
    } catch (SAXException | ParserConfigurationException e) {
      logger.error("Exception", e);
    }

    return reader;
}

Задача :

После внесения исправления, я теперь получаюисключение unmarshal, когда программа пытается прочитать в XML:

javax.xml.bind.UnmarshalException: unexpected element (uri:"", local:"ns1:TypeXYZ"). Expected elements are <{protected namespace URI}TypeABC>,...<{protected namespace URI}TypeXYZ>,...

До исправления, описанного выше, где я только что использовал JAXB для отмены маршалинга, она могла правильно проанализировать предоставленный XML без проблем.

Я предполагаю, что синтаксический анализатор SAX ожидает, что XML предоставит дополнительную информацию, которая отсутствует, или что он должен быть сконфигурирован так, чтобы игнорировать все, на что он жалуется. Я попробовал несколько других «функций» (http://xml.org/sax/features/namespace-prefixes=true и http://xml.org/sax/features/validation=false),, но это не решило проблему.

У меня нет контроля над схемой XML, которая определяет типы XML, и при этом я не имею контроля над тем, как соответствующий Java классы создаются.

Любая информация, которая поможет мне понять, что происходит, и которая помогает мне решить эту проблему, будет очень цениться.

1 Ответ

0 голосов
/ 27 декабря 2018

После небольшого эксперимента мне удалось устранить ошибку, установив следующие функции:

factory.setFeature("http://xml.org/sax/features/validation", false);
factory.setFeature("http://xml.org/sax/features/namespaces", true);
factory.setFeature("http://xml.org/sax/features/namespace-prefixes", true);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...