401 error when consuming a Web service with HTTP Basic authentication using CXF

自作多情 提交于 2019-12-20 18:34:30

问题


I'm trying to consume a remote Web service that uses HTTP basic authentication, using Apache CXF, within a JUnit test.

The error I am getting is:

javax.xml.ws.WebServiceException: Failed to access the WSDL at: http://localhost:8080/services/MyService?wsdl. It failed with: 
    Server returned HTTP response code: 401 for URL: http://localhost:8080/services/MyService?wsdl.
    at com.sun.xml.internal.ws.wsdl.parser.RuntimeWSDLParser.tryWithMex(RuntimeWSDLParser.java:151)
    at com.sun.xml.internal.ws.wsdl.parser.RuntimeWSDLParser.parse(RuntimeWSDLParser.java:133)
    at com.sun.xml.internal.ws.client.WSServiceDelegate.parseWSDL(WSServiceDelegate.java:254)
    at com.sun.xml.internal.ws.client.WSServiceDelegate.<init>(WSServiceDelegate.java:217)
    at com.sun.xml.internal.ws.client.WSServiceDelegate.<init>(WSServiceDelegate.java:165)
    at com.sun.xml.internal.ws.spi.ProviderImpl.createServiceDelegate(ProviderImpl.java:93)
    at javax.xml.ws.Service.<init>(Service.java:76)
    at com.wave2.marketplace.importer.impl.adportal.ws.MyServiceService.<init>(MyServiceService.java:37)
    at com.wave2.marketplace.importer.impl.adportal.MyWSTest.testConsumingTheWS(MyWSTest.java:22)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:616)
    at junit.framework.TestCase.runTest(TestCase.java:168)
    at junit.framework.TestCase.runBare(TestCase.java:134)
    at junit.framework.TestResult$1.protect(TestResult.java:110)
    at junit.framework.TestResult.runProtected(TestResult.java:128)
    at junit.framework.TestResult.run(TestResult.java:113)
    at junit.framework.TestCase.run(TestCase.java:124)
    at junit.framework.TestSuite.runTest(TestSuite.java:232)
    at junit.framework.TestSuite.run(TestSuite.java:227)
    at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:83)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:46)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: java.io.IOException: Server returned HTTP response code: 401 for URL: http://localhost:8080/services/MyService?wsdl
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1269)
    at java.net.URL.openStream(URL.java:1029)
    at com.sun.xml.internal.ws.wsdl.parser.RuntimeWSDLParser.createReader(RuntimeWSDLParser.java:793)
    at com.sun.xml.internal.ws.wsdl.parser.RuntimeWSDLParser.resolveWSDL(RuntimeWSDLParser.java:251)
    at com.sun.xml.internal.ws.wsdl.parser.RuntimeWSDLParser.parse(RuntimeWSDLParser.java:118)
    ... 26 more

Having read this StackOverflow post, I have attempted to add the auth credentials to my request context, as follows:

@Test
public void testConsumingTheWS() throws Exception {
    URL wsdl = new URL("http://localhost:8080/services/MyService?wsdl");

    MyServiceService provider = new MyServiceService(wsdl); // <-- Error occurs here
    MyService service = provider.getMyService();

    BindingProvider binding = (BindingProvider)service;
    binding.getRequestContext().put(BindingProvider.USERNAME_PROPERTY, "username");
    binding.getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, "password");

    Ping out = service.getPing();
    assertNotNull(out);
}

However, as my in-line comment indicates, the error is occurring before the BindingProvider code is reached, so the error remains the same.

I did have a read of this article and its follow-up, but so far I've had trouble determining how to go about adding the interceptor code without the use of Spring (this is for a JUnit test).

How might I go about authenticating against this Web service?


回答1:


According to HTTP basic authentication with JAX-WS (Client):

2. The service class creation

A constructor of the service object requires access to the WSDL. And again it does not support basic authentication out of the box. You have an option to download the wsdl file and use it locally. Another option is to use the default authenticator:

Authenticator.setDefault(new Authenticator() {
    @Override
    protected PasswordAuthentication getPasswordAuthentication() {
        return new PasswordAuthentication(
            USER_NAME,
            PASSWORD.toCharArray());
    }
});



回答2:


Just a point of note, you aren't using CXF. You are using the JAX-WS reference implementation built into the JDK.

With CXF, you CAN use Spring config for everything and not set the default Authenticator. See the page at:

http://cxf.apache.org/docs/client-http-transport-including-ssl-support.html

about the http-conf:authorization settings.



来源:https://stackoverflow.com/questions/3037221/401-error-when-consuming-a-web-service-with-http-basic-authentication-using-cxf

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!