JAX-WS Metro, как перехватить правильное зашифрованное/подписанное сообщение с недопустимыми символами/несоответствием подписи

Мой вопрос связан с этим

У меня были недели головной боли, чтобы попытаться бороться с этим, но, похоже, не существует решения, достойного упоминания, кроме решения вышеуказанного вопроса, который является ужасным обходным путем, но на самом деле кажется, что ничего другого вокруг не существует. .

Мы пытаемся связаться с устаревшей системой, в которой есть установленная и работающая веб-служба с определенными ограничениями WS-Security, объявленными в ее WSDL. Мы не можем ничего изменить на сервере, мы просто должны делать то, что он предлагает. У нас также есть сторонняя реализация клиента, которая на самом деле работает и взаимодействует с сервером, поэтому мы знаем, что связь работает - с использованием ЭТОГО конкретного клиента. Теперь мы хотим сделать свой собственный.

Приведенная выше политика WS-Security включает шифрование и подпись. Были следующие сценарии того, что делать:

  • написать собственный код для шифрования/дешифрования и подписи/проверки
  • используйте одну из готовых реализаций JAX-WS, чтобы сделать это за нас

Второй вариант, конечно, то, что мы пытались сделать. Затем мы переходим к следующему:

  • Метро/WSIT
  • Апач CXF

Все в Интернете предлагают последний вариант (который я тоже пробовал), но пока я выбрал первый (тем более, что у нас нет интеграции со Spring, чтобы воспользоваться хорошей интеграцией с ним CXF)

После борьбы с неоднозначной документацией и различными мастерами (NetBeans) мы пришли к решению, которое содержало очень мало пользовательского кода, файл конфигурации с некоторыми хранилищами ключей и обычный сгенерированный код из утилиты wsimport.

По прошествии некоторого времени он включал дамп запросов и ответов XML SOAP, сравнивая неудачные запросы, которые мы производим, с успешными от стороннего клиента. Много боли, но безрезультатно — сообщения были разными, но основная логика и структура были в порядке — тогда вы не могли сравнивать зашифрованные части. Через какое-то время у меня появился клиент, который что-то отправил и что-то получил в ответ, но не смог расшифровать ответ.

На самом деле он был расшифрован нормально, но проверка дайджеста подписи не удалась. Стоит отметить, что исходное XML-сообщение содержало символ «&», а также несколько символов новой строки. т.е. полезная нагрузка сообщения SOAP не была синтаксически корректной XML. В любом случае.

Похоже, что эта проверка дайджеста глубоко укоренилась в стеке Metro/WSIT, и я не мог найти способа перехватить и исправить этот дайджест — или фактически содержимое, на основе которого этот дайджест был рассчитан — очевидно — проблема заключалась в том, что какой-то особый символы были переведены или канонизированы либо после, либо до вычисления дайджеста, и мы (скорее базовая реализация, которую я пытался использовать, чтобы держать руки в чистоте) делали что-то отличное от того, что делала серверная часть веб-службы.

Даже трубы Metro (красивое название, но ужасающе скудная документация — кажется, что сегодня никто не использует Metro/WSIT — или, лучше сказать, никто не использует SOAP или SOAP с таким уровнем безопасности? — когда я попробовал Apache CXF, сгенерированные сообщения SOAP были обманчиво похожи), и их способ перехвата сообщений, похоже, не помог - при попытке получить необработанное содержимое сообщения не было предоставленных методов (Packet.getMessage().writeTo... - и другие варианты) на самом деле может обойти проверку дайджеста - потому что они ВСЕ пытались прочитать содержимое способом StAX, потоковой передачей и т. д. (вызывая StreamingPayLoadDigester.accept, который неизменно терпел неудачу)

Но надежда умирала последней, и я снова и снова пытался найти какую-нибудь неизвестную недокументированную магию, чтобы заставить свое дело работать. Хорошо, я собирался положить этому конец и усердно копаться в Java-шифровании, пока не нашел вышеупомянутый вопрос, то есть. На самом деле он «эксплуатирует» сообщение журнала, которое печатается из глубины кода Metro (на самом деле, я думаю, из wssx-impl) с канонизированным расшифрованным сообщением, прежде чем генерировать исключение несоответствия дайджеста. К счастью, это сообщение печатается с помощью java.util.logging, и его можно перехватить различными способами, например. отправить его в какую-то синхронизированную очередь для использования моим клиентом. Фу. Если у кого-то есть идея получше, пишите свои мысли.

Спасибо вам всем.


person hello_earth    schedule 14.05.2019    source источник


Ответы (1)


Наконец, я прибегнул к перестройке Metro/WSIT версии 2.1.1, найденной на GitHub, комментируя одну строку в проекте реализации WS-SX (ws-sx\wssx-impl...\StreamingPayloadDigester.java:145).

if (!Arrays.equals(originalDigest, calculatedDigest)) {
    XMLSignatureException xe = new XMLSignatureException(LogStringsMessages.WSS_1717_ERROR_PAYLOAD_VERIFICATION());
    logger.log(Level.WARNING, LogStringsMessages.WSS_1717_ERROR_PAYLOAD_VERIFICATION()); //,xe);
    // bypass throwing exception
    // throw new WebServiceException(xe);
}

Можно было сделать лучше, например, поставить флаг.

Порядок проектов, начиная с самого маленького, в котором я внес изменения, до того, который я включаю в свой собственный проект в качестве реализации Metro, примерно следующий:

  1. Реализация WS-SX упоминается в ->
  2. Ссылка на проект WS-Security находится в ->
  3. Ссылка на пакет реализации технологии взаимодействия веб-сервисов Metro (wsit-impl) находится в ->
  4. Пакет Metro Web Serrvices Runtime без OSGi (webservices-rt), включенный в мой клиент
person hello_earth    schedule 29.07.2019