Я пытаюсь разработать клиент веб-службы для: https://se-face-webservice.redsara.es/facturasspp2?wsdl Безопасность реализована с помощью профиля токена WS-Security 1.0 X.509
Я уже попробовал три подхода :
1) Просто с включенными библиотеками в Java 1.8 и Wsdl2 Java. (JAX-WS?) После большого количества глажения я смог включить сертификат и отправить запрос, но сервер отвечает пользовательской ошибкой «Signature not valid».
2) Axis2, после использования мастера Eclipse 2019-09, я обнаружил, что он слишком сильно портится с моим текущим проектом: много новых jar и новых папок. Слишком много, когда этот веб-сервис включает только около 1% элементов системы.
3) Ось (не рекомендуется) Я использовал мастер Eclipse 2019-09: сначала я обнаружил пару пропавших классов, Похоже, волшебник не добавляет все банки. Я решил это, загрузив wss4j-1.5.8 & xmlse c -1.4.4 (не могу быть уверен, что эти версии работают хорошо с осью 1.4, но ошибки исчезли). После выяснения, как включить сертификат, реализующий обработчик Basi c, я получаю успешный ответ от сервера (я печатаю его на консоль), но при разборе я получаю:
faultCode: {http://schemas.xmlsoap.org/soap/envelope/}MustUnderstand
faultSubcode:
faultString: Did not understand "MustUnderstand" header(s):{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd}Security
I В подходе № 1 была похожая или, возможно, такая же ошибка, которую я исправил с помощью первого ответа в SOAPFaultException: «Заголовки MustUnderstand (oasis-200401-wss-wssecurity-secext-1.0.xsd) не поняты» , но Я не знаю, как применить это в сгенерированном коде оси.
Здесь много сообщений в stackoverflow об этой ошибке с осью, но большинство об отключении этой опции в запросе. Кажется, в этом В этом случае я думаю, что сервер работает с MustUnderstand = '1'. В любом случае, мой запрос не включал MustUnderstand в wsse, поэтому я попытался с
_call.setProperty(org.apache.axis.client.Call.CHECK_MUST_UNDERSTAND, Boolean.TRUE)
, но он не сработал. Единственный способ, которым я обнаружил включение Mustunderstand = "1" в свой запрос, - это код в BasicHandler:
WSSecHeader wsSecHeader;
wsSecHeader.setMustUnderstand(true);
...
, но получил ту же ошибку.
В настоящее время я пытаюсь найдите способ как-то обойти эту проверку MustUnderstand, перехватывая и преобразовывая ответ до его анализа. В методе вызова обработчика вы можете добиться этого перехвата:
public void invoke(MessageContext msgContext) throws AxisFault {
try {
//request, include signing with certificate in the header
((SOAPPart) msgContext.getRequestMessage().getSOAPPart()).setCurrentMessage(this.createBinarySecurityToken(msgContext),
SOAPPart.FORM_SOAPENVELOPE);
//response
if(msgContext.getResponseMessage() != null) {
String transf = msgContext.getResponseMessage().getSOAPPartAsString();
//
transf = transf.replace("mustUnderstand=\"1\"" , "");
msgContext.setResponseMessage(new Message(transf ));
}
//Print xml to console
if(msgContext.getResponseMessage() != null && msgContext.getResponseMessage().getSOAPPart() != null) {
System.out.println("\n -- RESPONSE -- \n" + msgContext.getResponseMessage().getSOAPPartAsString());
} else {
if(msgContext.getRequestMessage() != null && msgContext.getRequestMessage().getSOAPPartAsString() != null) {
System.out.println("\n -- REQUEST -- \n" + msgContext.getRequestMessage().getSOAPPartAsString());
}
}
} catch (Exception e) {
System.err.println(e.getMessage());
System.exit(-1);
}
}
Как вы можете видеть, я наивно думал, что удаление части mustUnderstand из xml будет работать, но я получаю 'SimpleDeserializer, обнаруживший дочерний элемент, что НЕ ожидается, в чем-то, что он пытался десериализовать ».
Я также пытался с чем-то, что нашел, но безуспешно:
SOAPHeader header = msgContext.getResponseMessage().getSOAPHeader();
if( header != null )
{
Iterator<?> blocks = header.examineAllHeaderElements();
while( blocks.hasNext() )
{
SOAPHeaderElement block = (SOAPHeaderElement)blocks.next();
block.setMustUnderstand(false);
}
}
Должен быть способ игнорировать эта проверка заголовка, потому что тело в ответе показывает ожидаемую информацию, оно там.
Я нашел обходной путь , но он очень грязный. Если я сделаю запрос с подходом № 3, а затем с подходом № 1, неожиданно № 1 теперь работает полностью. Вместо того, чтобы сервер отвечал «Подпись недействительна», я получил правильный ответ, и он анализируется сгенерированными классами. Последующие вызовы только с # 1 работают.
Это не постоянно, когда я пытаюсь на следующий день # 1 вернуться к ошибке, но выполнение обходных / конкатенационных вызовов снова исправляет это. Я уже видел это поведение в течение 3 дней подряд, я не могу понять это, но это может быть временное решение.
Тем временем я также сравню SOAP запросы 1 и 3, чтобы проверить различия в заголовке.