Axis2 Client Throws AxisFault: Must Understand check failed for header Security
Asked Answered
D

1

6

I'm using Axis2-1.6.1 and have been able to successfully send a SOAP request. Here's an example of the request:

<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope">
  <soapenv:Header>
    <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" soapenv:mustUnderstand="true">
      <wsse:UsernameToken xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
        <wsse:Username>***username***</wsse:Username>
        <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">***pass***</wsse:Password>
        <wsse:Nonce Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">***nonce***</wsse:Nonce>
        <wsu:Created Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">***datetime***</wsu:Created>
      </wsse:UsernameToken>
    </wsse:Security>
    <wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">http://mysite/contract/users/v3/IUsers/EchoAuthenticated</wsa:Action>
  </soapenv:Header>
  <soapenv:Body>
    <ns6:EchoAuthenticated xmlns:ns6="http://mysite/contract/users/v3">
      <ns6:value>success</ns6:value>
    </ns6:EchoAuthenticated>
  </soapenv:Body>
</soapenv:Envelope>

Upon receiving the response, this exception is thrown:

org.apache.axis2.AxisFault: Must Understand check failed for header http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd : Security

I'm under the impression, after doing some research, that there's something in the response that Axis2 doesn't like. Puzzled, I copied the above request and pasted it into SoapUI and fired it. It works, I receive the below response. I also confirmed, using Fiddler, that this is the same response I am getting when I send this request in Eclipse its just there's something about it that Axis2 doesn't like client-side, perhaps the mustUnderstand?

Here's the response:

<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
  <s:Header>
    <a:Action s:mustUnderstand="1">http://mysite/contract/users/v3/IUsers/EchoAuthenticatedResponse</a:Action>
    <a:RelatesTo>urn:uuid:***guid***</a:RelatesTo>
    <o:Security s:mustUnderstand="1" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
      <u:Timestamp u:Id="_0">
        <u:Created>***datetime***</u:Created>
        <u:Expires>***datetime***</u:Expires>
      </u:Timestamp>
    </o:Security>
  </s:Header>
  <s:Body>
    <EchoAuthenticatedResponse xmlns="http://mysite/contract/users/v3">
      <EchoAuthenticatedResult>This is the Users service answering back. The value you sent was: success</EchoAuthenticatedResult>
    </EchoAuthenticatedResponse>
  </s:Body>
</s:Envelope>

I'm limited in my ability to move to a more recent version of Axis2 as this is bundled with a product but I need to find out how I can get passed this error.

Drivein answered 8/1, 2018 at 22:4 Comment(0)
D
9

I found one solution which is to set mustUnderstand instances in the response to false

To accomplish this I've done the following:


  1. Create a Handler class which extends *org.apache.axis2.handlers.AbstractHandler

MustUnderstandHandler.java

import java.util.Iterator;

import org.apache.axiom.soap.SOAPEnvelope;
import org.apache.axiom.soap.SOAPHeader;
import org.apache.axiom.soap.SOAPHeaderBlock;
import org.apache.axis2.AxisFault;
import org.apache.axis2.context.MessageContext;

public class MustUnderstandHandler extends org.apache.axis2.handlers.AbstractHandler  {

  @Override
  public InvocationResponse invoke(MessageContext messageContext) throws AxisFault {
    
    try{
      
      System.out.println("RemoveMustUnderstandAll: invoke " + messageContext);
      
      SOAPEnvelope env = messageContext.getEnvelope();
      SOAPHeader header = env.getHeader();
      
      if(header != null){
        
          for(Iterator<?> itr = header.getChildElements(); itr.hasNext();){
            
              SOAPHeaderBlock headerBlock = (SOAPHeaderBlock) itr.next();
              
              if(headerBlock.getMustUnderstand()){
                
                headerBlock.setMustUnderstand(false);
                System.out.println("RemoveMustUnderstandAll (" + messageContext + "): setMustUnderstand(false) to " + headerBlock.getQName());
              }
          }
      }
    }
    catch(Exception e){

      System.out.println(e.toString());
    }
    
    return InvocationResponse.CONTINUE;
  }
}

  1. Wire the AxisConfiguration to use the handler class

In the generated Stub (created from WSDL2Java) I've located instances where it's executing the client and before each of these lines I included the following:

MyStub.java

AxisConfiguration axisConfiguration = _messageContext.getConfigurationContext().getAxisConfiguration();
ArrayList arrayList = new ArrayList();
arrayList.add(new MustUnderstandHandler());
axisConfiguration.setInPhasesUptoAndIncludingPostDispatch(arrayList);

// execute the operation client
_operationClient.execute(true);
Drivein answered 9/1, 2018 at 23:45 Comment(2)
As for the second part (wire the AxisConfiguration...) it didn't work for me, but you helped me a lot to get to this solution: AxisConfiguration axisConfiguration = _messageContext.getConfigurationContext().getAxisConfiguration(); List<Phase> outPhases = axisConfiguration.getOutFlowPhases(); for(Phase p : outPhases) { if ("Security".equals(p.getPhaseName())) { p.addHandler(new MustUnderstandHandler(), p.getHandlerCount()); } } // execute the operation client _operationClient.execute(true);Ruck
I successfully applied your approach to a client: List<Phase> phases = axisConfiguration.getOutFlowPhases(); Phase phase = new Phase(); phase.addHandler(new SetSecurityMustUnderstandAttribute()); phases.add(phase); axisConfiguration.setGlobalOutPhase(phases); Thank you very much!Postliminy

© 2022 - 2024 — McMap. All rights reserved.