简体   繁体   中英

WS Security Error: 181001 while trying to access to a web service through Apache CXF

I have successfuly generated Java classes using wsdl2java. Now I am trying to build a client for accessing the web service. I am using Apache CXF for that. On trying to connect, I get the following error:

Exception in thread "main" javax.xml.ws.soap.SOAPFaultException: WS Security Error : 181001
    at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:155)
    at $Proxy36.getCustomerOp(Unknown Source)
    at com.ievgen.webservices.TestClient4.main(TestClient4.java:87)
Caused by: org.apache.cxf.binding.soap.SoapFault: WS Security Error : 181001
    at org.apache.cxf.binding.soap.interceptor.Soap11FaultInInterceptor.unmarshalFault(Soap11FaultInInterceptor.java:75)
    at org.apache.cxf.binding.soap.interceptor.Soap11FaultInInterceptor.handleMessage(Soap11FaultInInterceptor.java:46)
    at org.apache.cxf.binding.soap.interceptor.Soap11FaultInInterceptor.handleMessage(Soap11FaultInInterceptor.java:35)
    at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:271)
    at org.apache.cxf.interceptor.AbstractFaultChainInitiatorObserver.onMessage(AbstractFaultChainInitiatorObserver.java:114)
    at org.apache.cxf.binding.soap.interceptor.CheckFaultInterceptor.handleMessage(CheckFaultInterceptor.java:69)
    at org.apache.cxf.binding.soap.interceptor.CheckFaultInterceptor.handleMessage(CheckFaultInterceptor.java:34)
    at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:271)
    at org.apache.cxf.endpoint.ClientImpl.onMessage(ClientImpl.java:800)
    at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponseInternal(HTTPConduit.java:1592)
    at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponse(HTTPConduit.java:1490)
    at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.close(HTTPConduit.java:1309)
    at org.apache.cxf.transport.AbstractConduit.close(AbstractConduit.java:56)
    at org.apache.cxf.transport.http.HTTPConduit.close(HTTPConduit.java:622)
    at org.apache.cxf.interceptor.MessageSenderInterceptor$MessageSenderEndingInterceptor.handleMessage(MessageSenderInterceptor.java:62)
    at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:271)
    at org.apache.cxf.endpoint.ClientImpl.doInvoke(ClientImpl.java:530)
    at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:463)
    at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:366)
    at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:319)
    at org.apache.cxf.frontend.ClientProxy.invokeSync(ClientProxy.java:96)
    at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:133)
    ... 2 more

According to what I have found on the web, the 181001 error means that the required authentification block is missing. However, I've configured the username and password as described in documentation: http://cxf.apache.org/docs/ws-secureconversation.html

Here is my code:

package com.ievgen.webservices;

import java.io.File;

import javax.net.ssl.*;
import javax.xml.ws.BindingProvider;
import java.net.MalformedURLException;
import java.net.URL;

import org.apache.cxf.configuration.jsse.TLSClientParameters;
import org.apache.cxf.endpoint.Client;
import org.apache.cxf.frontend.ClientProxy;
import org.apache.cxf.transport.http.HTTPConduit;

import info.app.catalogservices.schemas.customerquery_1.CustomerQueryType;
import info.app.catalogservices.services.csscatalogservicesinterface_1_0.CustomerError;
import info.app.catalogservices.services.csscatalogservicesinterface_1_0.IntfCatalogServicesService;
import info.app.catalogservices.services.csscatalogservicesinterface_1_0.PortType;

public class TestClient4 {

    /**
     * @param args
     * @throws MalformedURLException
     */
    public static void main(String[] args) throws MalformedURLException {
        // Create a trust manager that does not validate certificate chains
        TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
            public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                return null;
            }

            public void checkClientTrusted(
                    java.security.cert.X509Certificate[] certs, String authType) {
            }

            public void checkServerTrusted(
                    java.security.cert.X509Certificate[] certs, String authType) {
            }
        } };

        // TODO Auto-generated method stub
        File wsdlFile = new File("WebContent/CatalogServices-1.1.0.wsdl");
        URL wsdlUrl = null;
        if (wsdlFile.exists()) {
            wsdlUrl = wsdlFile.toURL();
        } else {
            System.out.println("File doesn't exist");
        }

        System.out.println("WSDL url: " + wsdlUrl);
        IntfCatalogServicesService service = new IntfCatalogServicesService(
                wsdlUrl);
        PortType portType = service.getPortTypeEndpoint();

        // This will configure the http conduit dynamically
        Client client = ClientProxy.getClient(portType);

        client.getRequestContext().put("ws-security.username", "username");
        client.getRequestContext().put("ws-security.password", "password");

        HTTPConduit http = (HTTPConduit) client.getConduit();

        TLSClientParameters tlsParams = new TLSClientParameters();
        // set trust manager which trusts to all certificates
        tlsParams.setTrustManagers(trustAllCerts);
        // The certificate provides another CN that it really is, so disable
        // CNcheck
        tlsParams.setDisableCNCheck(true);

        http.setTlsClientParameters(tlsParams);

        String resp;
        CustomerQueryType customerQuery = new CustomerQueryType();
        customerQuery.setCustomer("0056712120");
        java.util.Map<String,Object> requestContext = ((BindingProvider) portType)
                .getRequestContext();
            //I set username/password twice because I am not sure where to do it better
            //I have found different directions in different sources
        requestContext.put("ws-security.username", "username");
        requestContext.put("ws-security.password", "password");
        requestContext
                .put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY,
                        "https://host:port/Services/intfCatalogServices-service.serviceagent/portTypeEndpoint");

        try {
            resp = portType.getCustomerOp(customerQuery).toString();
            System.out.println(resp);
        } catch (CustomerError e) {
            e.printStackTrace();
        }
    }

}

Note: I am able to access the web service using SOAP UI.

Could you please tell me what am I missing here?

EDIT: Here: http://cxf.apache.org/docs/ws-secureconversation.html it is said that it's neccessary to set "ws-security.username.sct:. On the other hand, here: http://cxf.apache.org/docs/ws-securitypolicy.html it is said to set "ws-security.username". I've tried both variants, but neither of them worked for me.

Does the WSDL you are using have a WS-Policy fragment in there that describes the security requirements? If it doesn't then the WS-SecurityPolicy properties wouldn't be applied as the policies in effect don't mention anything related to security.

If there isn't any security related policies, you will need to drop to hand configuration of the WSS4J interceptors. See http://cxf.apache.org/docs/ws-security.html

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM