web-dev-qa-db-fra.com

SOAPFaultException "Les en-têtes MustUnderstand (oasis-200401-wss-wssecurity-secext-1.0.xsd) ne sont pas compris"

J'essaie d'obtenir des informations d'un service Web utilisant le type PasswordText WSS. Tout d'abord, je l'ai testé avec soapUI et j'ai réussi à obtenir des données. Ensuite, j'ai implémenté l'authentification sur Java en écrivant 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;
}

...
}

J'ai vérifié l'objet doc avec XMLUtils.PrettyDocumentToString(doc) et j'ai vu qu'il ressemblait au XML envoyé par soupUI. Toutes les informations d'authentification (nom d'utilisateur, mot de passe, heure de création) étaient sur place, mustUnderstand attribut de la variable Security était vrai.

Alors j'ai fait face à l'erreur:

javax.xml.ws.soap.SOAPFaultException: en-têtes MustUnderstand: [{ http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd } Sécurité] ne sont pas compris

J'ai trouvé des conseils pour supprimer l'attribut mustUnderstand de la balise Security, mais cela n'aide pas. Avez-vous des idées?

P.S.

Le point de terminaison du service Web est sur HTTPS.

Partie politique de 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 demande:

<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>[email protected]</ns:email>
            <ns:firstName/>
            <ns:lastName/>
        </ns:RetrieveCustomerByEmail>
    </soapenv:Body>
</soapenv:Envelope>

Ma demande:

<?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>[email protected]</ns5:email>
            <ns5:firstName/>
            <ns5:lastName/>
        </ns5:RetrieveCustomerByEmail>
    </S:Body>
</S:Envelope>
17
Marboni

J'ai trouvé la solution. Les dépendances suivantes étaient nécessaires:

<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>

Bon article sur ce sujet et quelques pièges de cxf: http://www.logicsector.com/Java/how-to-create-a-wsdl-first-soap-client-in-Java-with-cxf-and -maven/

8
Marboni

Vous pouvez obtenir cette erreur lorsque le service ne gère pas les en-têtes. Le service doit implémenter un SOAPHandler avec un getHeaders () qui résoudrait les en-têtes. Pour le défaut mentionné ci-dessus, la mise en œuvre correcte serait la suivante

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

Il est également possible de l'obtenir lorsque le service n'est pas sécurisé, mais que le client tente d'utiliser une configuration de sécurité (éventuellement en utilisant une configuration de sécurité XWSS). contient la politique de sécurité attendue (ajoutez? wsdl à son URL de noeud final)

14
Joseph Rajeev Motha

Voici ce qui a fonctionné pour moi. En gros, c’est une application de l’idée exprimée par @Joseph Rajeev Motha (bien que je l’aie trouvée ailleurs, ici: https://dwuysan.wordpress.com/2012/04/02/jax-ws-wsimport-and-the -error-mustunderstand-headers-not-includes/# comment-215 ), mais sa réponse ne fournit pas de passe-partout, et sans cela, la réponse est assez mystérieuse.

Veuillez noter que cette séquence s'applique au cas autonome (où vous publiez vous-même une Endpoint).

Étape 1

Créez une SOAPHandler qui "comprendra" l'en-tête:

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

Étape 2

Créez un fichier handler-chain.xml et placez-le sur 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>

Étape 3

Annotez votre classe d'implémentation (classe annotée avec @WebService) avec une référence au fichier de chaîne du gestionnaire:

@HandlerChain(file = "handler-chain.xml")

Étape 4

Publiez votre terminal:

Endpoint endpoint = Endpoint.publish(url, impl);

Une note importante

handleMessage() et handleFault() définis par le gestionnaire doivent renvoyer true. Sinon, vous obtiendrez des erreurs étranges telles que 'Elément de wrapper inattendu' car un nom d'élément de wrapper différent sera utilisé.

0
Roman Puchkovskiy