SOAPFaultException “MustUnderstand intestazioni (oasi-200401-wss-wssecurity-secext-1.0.xsd) non sono capito”
-
28-10-2019 - |
Domanda
Cerco di ottenere informazioni dal servizio web che utilizza PasswordText WSS tipo.In primo luogo, I test utilizzando soapUI e successo ha dati.Poi ho implementato l'autenticazione su Java, scrittura SecurityHandler:
public final class SecurityHandler implements SOAPHandler<SOAPMessageContext> {
...
@Override
public boolean handleMessage(SOAPMessageContext messageContext) {
boolean outInd = (Boolean) messageContext.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
if (outInd) {
try {
WSSecUsernameToken builder = new WSSecUsernameToken();
builder.setPasswordType(WSConstants.PASSWORD_TEXT);
builder.setUserInfo(_username, _password);
builder.addNonce();
builder.addCreated();
Document doc = messageContext.getMessage().getSOAPPart().getEnvelope().getOwnerDocument();
WSSecHeader secHeader = new WSSecHeader();
secHeader.insertSecurityHeader(doc);
builder.build(doc, secHeader);
} catch (Exception e) {
LOGGER.error("Unable to handle SOAP message", e);
return false;
}
}
return true;
}
...
}
Ho controllato oggetto doc con XMLUtils.PrettyDocumentToString(doc)
e visto che piace XML inviato da soupUI - tutte le informazioni di autenticazione (login, password, nonce e ha creato il tempo) erano sul posto, mustUnderstand attributo di Security
tag era vero.
Poi ho affrontato con l'errore:
javax.xml.ws.il sapone.SOAPFaultException:MustUnderstand intestazioni:[{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd}Di sicurezza] non sono capito
Ho trovato consigli per rimuovere mustUnderstand attributo Security
tag, ma non aiuta.Avete idee?
P. S.
Endpoint del servizio Web è HTTPS.
La politica parte dal WSDL:
<wsp:Policy wsu:Id="BasicHttpBinding_RelateService_policy">
<wsp:ExactlyOne>
<wsp:All>
<sp:TransportBinding>
<wsp:Policy>
<sp:TransportToken>
<wsp:Policy>
<sp:HttpsToken RequireClientCertificate="false"/>
</wsp:Policy>
</sp:TransportToken>
<sp:AlgorithmSuite>
<wsp:Policy>
<sp:Basic256/>
</wsp:Policy>
</sp:AlgorithmSuite>
<sp:Layout>
<wsp:Policy>
<sp:Lax/>
</wsp:Policy>
</sp:Layout>
<sp:IncludeTimestamp/>
</wsp:Policy>
</sp:TransportBinding>
<sp:SignedSupportingTokens>
<wsp:Policy>
<sp:UsernameToken
sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/AlwaysToRecipient">
<wsp:Policy>
<sp:WssUsernameToken10/>
</wsp:Policy>
</sp:UsernameToken>
</wsp:Policy>
</sp:SignedSupportingTokens>
<sp:Wss10>
<wsp:Policy/>
</sp:Wss10>
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>
soapUI richiesta:
<soapenv:Envelope xmlns:ns="http://api.example.com/RelateService/1.0"
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header>
<wsse:Security soapenv:mustUnderstand="1"
xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<wsse:UsernameToken wsu:Id="UsernameToken-37"
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">
password
</wsse:Password>
<wsse:Nonce
EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">
li/0YK2wxrmrHL7Cg+etdQ==
</wsse:Nonce>
<wsu:Created>2012-02-21T08:59:10.262Z</wsu:Created>
</wsse:UsernameToken>
</wsse:Security>
</soapenv:Header>
<soapenv:Body>
<ns:RetrieveCustomerByEmail>
<ns:email>xxx@example.com</ns:email>
<ns:firstName/>
<ns:lastName/>
</ns:RetrieveCustomerByEmail>
</soapenv:Body>
</soapenv:Envelope>
La mia richiesta:
<?xml version="1.0" encoding="UTF-8"?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Header>
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
S:mustUnderstand="1">
<wsse:UsernameToken wsu:Id="UsernameToken-1">
<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">
password
</wsse:Password>
<wsse:Nonce
EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">
+jeleKO9zr0/wLjAIYcmSg==
</wsse:Nonce>
<wsu:Created>2012-02-21T09:42:03.760Z</wsu:Created>
</wsse:UsernameToken>
</wsse:Security>
</S:Header>
<S:Body>
<ns5:RetrieveCustomerByEmail xmlns="http://schemas.microsoft.com/2003/10/Serialization/Arrays"
xmlns:ns2="http://schemas.datacontract.org/2004/07/XXX.Service"
xmlns:ns3="http://schemas.datacontract.org/2004/07/XXX.Service.Relate.Contract"
xmlns:ns4="http://schemas.datacontract.org/2004/07/XXX.Service.Dto"
xmlns:ns5="http://api.example.com/RelateService/1.0"
xmlns:ns6="http://schemas.microsoft.com/2003/10/Serialization/">
<ns5:email>xxx@example.com</ns5:email>
<ns5:firstName/>
<ns5:lastName/>
</ns5:RetrieveCustomerByEmail>
</S:Body>
</S:Envelope>
Soluzione 2
Ho trovato la soluzione.Seguenti dipendenze, sono richiesti:
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxws</artifactId>
<version>2.2.3</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http</artifactId>
<version>2.2.3</version>
</dependency>
Buon articolo su questo argomento e alcune insidie di cxf: http://www.logicsector.com/java/how-to-create-a-wsdl-first-soap-client-in-java-with-cxf-and-maven/
Altri suggerimenti
È possibile ottenere questo errore quando il servizio non gestisce le intestazioni. Il servizio deve implementare un Soaphandler con un Getheaders () che risolverebbe le intestazioni. Per il guasto sopra menzionato l'implementazione corretta sarebbe la seguente
@Override
public Set<QName> getHeaders() {
QName securityHeader = new QName("http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd",
"Security");
HashSet<QName> headers = new HashSet<QName>();
headers.add(securityHeader);
return headers;
}
È anche possibile ottenerlo quando il servizio in realtà non è sicuro, ma il client sta tentando di utilizzare la configurazione di sicurezza (eventualmente utilizzando una configurazione di sicurezza XWSS) per questo, basta controllare il WSDL pubblicato da un browser e assicurarsi che contenga il previsto Politica di sicurezza (append? WSDL al suo URL endpoint)
Ecco cosa ha funzionato per me. Fondamentalmente, è un'applicazione dell'idea pronunciata da @joseph Rajeev Motha (anche se l'ho trovata altrove, qui: https://dwuysan.wordpress.com/2012/04/02/jax-ws-wsimport-and-the-error-mustunderstand-headers-not-understrsood/#comment-215 ), ma la sua risposta non fornisce piastra e senza di essa, la risposta è piuttosto misteriosa.
Si prega di notare che questa sequenza si applica al caso autonomo (in cui pubblichi un Endpoint
te stesso).
Passo 1
Creare un SOAPHandler
che "capirà" l'intestazione:
public class WSSESecurityUnderstandPretender implements SOAPHandler<SOAPMessageContext> {
@Override
public Set<QName> getHeaders() {
final QName securityHeader = new QName(
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd",
"Security",
"wsse");
final Set<QName> headers = new HashSet<>();
headers.add(securityHeader);
// notify the runtime that this is handled
return headers;
}
@Override
public boolean handleMessage(SOAPMessageContext context) {
// we must return true, or else the runtime will return
// wrong wrapper element name (like makeTransfer instead of
// makeTransferResponse)
return true;
}
@Override
public boolean handleFault(SOAPMessageContext context) {
// we must return true, or else the runtime will return
// wrong wrapper element name (like makeTransfer instead of
// makeTransferResponse)
return true;
}
@Override
public void close(MessageContext context) {
}
}
Passo 2
Creare un handler-chain.xml
File e mettilo su ClassPath:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<javaee:handler-chains
xmlns:javaee="http://java.sun.com/xml/ns/javaee"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<javaee:handler-chain>
<javaee:handler>
<javaee:handler-class>com.mypackage.WSSESecurityUnderstandPretender</javaee:handler-class>
</javaee:handler>
</javaee:handler-chain>
</javaee:handler-chains>
Passaggio 3
Annotare la tua classe di implementazione (classe che è annotata @WebService
) con un riferimento al file della catena del gestore:
@HandlerChain(file = "handler-chain.xml")
Passaggio 4
Pubblica il tuo endpoint:
Endpoint endpoint = Endpoint.publish(url, impl);
Una nota importante
handleMessage()
e handleFault()
definito dal gestore deve tornare true
. Altrimenti, otterrai strani errori come "Elemento wrapper inaspettato" perché verrà utilizzato un nome di elemento wrapper diverso.