jax example ejemplo consumir consume con autenticacion java webservice-client wss4j

example - ws-security java



SOAPFaultException "Los encabezados MustUnderstand(oasis-200401-wss-wssecurity-secext-1.0.xsd) no se entienden" (3)

Intento obtener información de un servicio web que usa el tipo de contraseña de texto WSS. En primer lugar, lo probé con soapUI y obtuve datos con éxito. Luego implementé la autenticación en Java, escribiendo 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; } ... }

XMLUtils.PrettyDocumentToString(doc) objeto doc con XMLUtils.PrettyDocumentToString(doc) y vi que se parece al XML enviado por soupUI: toda la información de autenticación (inicio de sesión, contraseña, hora y hora de creación) estaba vigente, el atributo mustUnderstand de Security etiqueta de Security era verdadero.

Entonces me enfrenté con el error:

javax.xml.ws.soap.SOAPFaultException: MustUnderstand headers: [{ http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd } Security] son no se entiende

Encontré consejos para eliminar el atributo mustUnderstand de Security etiqueta de Security , pero no ayuda. ¿Tienes alguna idea?

PD

El punto final del servicio web está en HTTPS .

Parte de la política 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>

solicitud de soapUI:

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

Mi petición:

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


Encontré la solución. Se requirieron las siguientes dependencias:

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

Buen artículo sobre este tema y algunos escollos de cxf: http://www.logicsector.com/java/how-to-create-a-wsdl-first-soap-client-in-java-with-cxf-and-maven/


Esto es lo que funcionó para mí. Básicamente, es una aplicación de la idea pronunciada por @Joseph Rajeev Motha (aunque la encontré en otro lugar, aquí: https://dwuysan.wordpress.com/2012/04/02/jax-ws-wsimport-and-the-error-mustunderstand-headers-not-understood/#comment-215 ), pero su respuesta no proporciona repetitivo, y sin ella, la respuesta es bastante misteriosa.

Tenga en cuenta que esta secuencia se aplica al caso independiente (donde usted mismo publica un Endpoint ).

Paso 1

Cree un SOAPHandler que "entienda" el encabezado:

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

Paso 2

Cree un archivo handler-chain.xml y póngalo en 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>

Paso 3

Anote su clase de implementación (clase que se anota con @WebService ) con una referencia al archivo de cadena de manejador:

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

Etapa 4

Publique su punto final:

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

Una nota importante

handleMessage() y handleFault() definidos por el controlador deben devolver true . De lo contrario, obtendrá errores extraños como "Elemento de envoltorio inesperado" porque se usará un nombre de elemento de envoltorio diferente.


Podría obtener este error cuando el servicio no maneje los encabezados. El servicio debe implementar un SOAPHandler con un getHeaders () que resolvería los encabezados. Para la falla arriba mencionada la implementación correcta sería la siguiente

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

También es posible obtener esto cuando el servicio en realidad no es seguro, pero el cliente está intentando usar la configuración de seguridad (posiblemente utilizando una configuración de seguridad XWSS). Para esto, simplemente verifique el wsdl publicado desde un navegador y asegúrese de que contenga la información esperada. política de seguridad (agregue wsdl a su URL de punto final)