Axis Web服务客户端,忽略mustUnderstand检查

时间:2020-01-17 11:46:01

标签: java web-services ws-security

我正在尝试为以下网站开发Web服务客户端:https://se-face-webservice.redsara.es/facturasspp2?wsdl 使用WS-Security 1.0 X.509令牌配置文件实现安全性

我已经尝试了三种方法:

1)仅包含Java 1.8和Wsdl2Java中包含的库。 (JAX-WS?) 经过大量熨烫后,我能够包含证书并发送请求,但是服务器响应“签名无效”自定义错误。

2)Axis2,在使用Eclipse 2019-09向导后,我发现它对我当前的项目造成了太多混乱:许多新的jar和新文件夹。当此Web服务仅涉及系统项目的1%时,实在太多了。

3)Axis(不建议使用)我使用了Eclipse 2019-09向导:首先,我发现了几个缺少的类,看起来该向导并未添加所有jar。 我下载了wss4j-1.5.8和xmlsec-1.4.4解决了这个问题(无法确定这些版本是否在1.4轴上工作良好,但错误消失了)。 在找出如何包括实现基本处理程序的证书之后,我从服务器获得了成功的响应(我正在将其打印到控制台),但是在解析时得到了:

 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 

在方法#1中,我在SOAPFaultException "MustUnderstand headers (oasis-200401-wss-wssecurity-secext-1.0.xsd) are not understood"中的第一个响应中解决了类似或相同的错误 但是我不知道如何在轴生成的代码中应用它。

在stackoverflow上有很多关于此轴错误的文章,但大多数是关于在请求中禁用此选项的。看来,在这种情况下,我认为服务器使用MustUnderstand ='1'。 无论如何,我的要求在wsse中没有包含MustUnderstand,因此我尝试了

_call.setProperty(org.apache.axis.client.Call.CHECK_MUST_UNDERSTAND, Boolean.TRUE)

但是没有用。我发现在请求中包括Mustunderstand =“ 1”的唯一方法是在BasicHandler中进行编码:

WSSecHeader wsSecHeader;
wsSecHeader.setMustUnderstand(true);
...

但出现相同的错误。

当前,我正在尝试找到一种方法,以某种方式绕过此MustUnderstand检查,在解析响应之前对其进行拦截和转换。在处理程序invoke方法中,您可以实现以下拦截:

   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);
        }
    }

您可以看到,我天真地认为从xml中删除mustUnderstand部分是可行的,但是我得到了“ 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返回错误,但是再次执行变通方法/连接调用可解决此问题。我已经连续三天看到这种行为,我听不懂,但这可能是一个临时解决方案。

同时,我还将比较1和3的SOAP请求,以检查标头中的差异。

0 个答案:

没有答案