Клиент JAX WS не может аутентифицироваться

Я пытаюсь использовать безопасный (https schema) веб-сервис с помощью стандартных инструментов JAVA 7 JAX WS. Этот веб-сервис требует аутентификации.

Я уже успешно добавил сертификат в хранилище ключей Java. Все необходимые классы, которые я создал из файла WSDL с помощью .

Теперь я пытаюсь использовать следующий вызов для запуска простого теста:

public class ReportingWebServiceTest {
    static ReportingServiceService service;
    static ReportingService port;

    @BeforeClass
    public static void setUpBeforeClass(){
        service = new ReportingServiceService();
        port = service.getReportingServicePort();
        Map<String, Object> rContext = ((BindingProvider) port).getRequestContext();
        Map<String, List<String>> headers = new HashMap<String, List<String>>();
        headers.put("Authorization", Collections.singletonList("Basic YWRtaW5AYWRhcHRsb2dpYy5jb206MTIxMjE****="));

//      headers.put("Username", Collections.singletonList("*****@******.com"));
//      headers.put("Password", Collections.singletonList("********"));
        rContext.put(MessageContext.HTTP_REQUEST_HEADERS, headers);
//      rContext.put(BindingProvider.USERNAME_PROPERTY, "*****@******.com");
//      rContext.put(BindingProvider.PASSWORD_PROPERTY, "********");
    }   

    @Test
    public void test() {
        WEBCAMPAIGNROW row = port.getCampaignRowById(14081);
        toConsole(row.toString());
    }

    protected static void toConsole(String msg) {
        System.out.println(msg);
    }
}

когда я запускаю тест, он дает мне следующее исключение:

javax.xml.ws.WebServiceException: Failed to access the WSDL at: https://reporting-stage.admp.mtv3.adtlgc.com/admp/ReportingService?wsdl. It failed with: 
    Got Server returned HTTP response code: 401 for URL: https://reporting-stage.admp.mtv3.adtlgc.com/admp/ReportingService?wsdl while opening stream from https://reporting-stage.admp.mtv3.adtlgc.com/admp/ReportingService?wsdl.
    at com.sun.xml.internal.ws.wsdl.parser.RuntimeWSDLParser.tryWithMex(RuntimeWSDLParser.java:173)
    at com.sun.xml.internal.ws.wsdl.parser.RuntimeWSDLParser.parse(RuntimeWSDLParser.java:155)
    at com.sun.xml.internal.ws.wsdl.parser.RuntimeWSDLParser.parse(RuntimeWSDLParser.java:120)
    at com.sun.xml.internal.ws.client.WSServiceDelegate.parseWSDL(WSServiceDelegate.java:257)
    at com.sun.xml.internal.ws.client.WSServiceDelegate.<init>(WSServiceDelegate.java:220)
    at com.sun.xml.internal.ws.client.WSServiceDelegate.<init>(WSServiceDelegate.java:168)
    at com.sun.xml.internal.ws.spi.ProviderImpl.createServiceDelegate(ProviderImpl.java:96)
    at javax.xml.ws.Service.<init>(Service.java:77)
    at com.enreach.admp.reporting.ReportingServiceService.<init>(ReportingServiceService.java:42)
    at me.enreach.automation.mtv3.ReportingWebServiceTest.setUpBeforeClass(ReportingWebServiceTest.java:26)
    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:606)
    at org.junit.runners.model.FrameworkMethod.runReflectiveCall(FrameworkMethod.java:47)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
    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: Got Server returned HTTP response code: 401 for URL: https://reporting-stage.admp.mtv3.adtlgc.com/admp/ReportingService?wsdl while opening stream from https://reporting-stage.admp.mtv3.adtlgc.com/admp/ReportingService?wsdl
    at com.sun.xml.internal.ws.wsdl.parser.RuntimeWSDLParser.createReader(RuntimeWSDLParser.java:842)
    at com.sun.xml.internal.ws.wsdl.parser.RuntimeWSDLParser.resolveWSDL(RuntimeWSDLParser.java:283)
    at com.sun.xml.internal.ws.wsdl.parser.RuntimeWSDLParser.parse(RuntimeWSDLParser.java:140)
    ... 23 more
Caused by: java.io.IOException: Server returned HTTP response code: 401 for URL: https://reporting-stage.admp.mtv3.adtlgc.com/admp/ReportingService?wsdl
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1626)
    at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:254)
    at java.net.URL.openStream(URL.java:1037)
    at com.sun.xml.internal.ws.wsdl.parser.RuntimeWSDLParser.createReader(RuntimeWSDLParser.java:827)
    ... 25 more

как вы видите, я попытался применить три разных метода аутентификации, но безуспешно. Исключение одинаково во всех трех случаях. Что я делаю не так?

P. S. Если я пытаюсь получить доступ к WSDL в браузере учетные данные, которые я использую в коде при этом работают нормально.

2 ответов


ваша проблема не связана с сертификатом SSL. Ваша проблема связана с аутентификацией. Экземпляр службы должен иметь доступ к содержимому WSDL (до вызова фактического веб-метода заглушки), но он не удался, поэтому вы получили эту ошибку.

у вас есть 2 решения:

  1. Регистрация аутентификатора по умолчанию:

    static {
    
        java.net.Authenticator.setDefault(new java.net.Authenticator() {
    
            @Override
            protected java.net.PasswordAuthentication getPasswordAuthentication() {
                return new java.net.PasswordAuthentication("myuser", "mypasswd".toCharArray());
            }
        });
    }
    
  2. загрузите документ WSDL и сохраните его в локальном хранилище, затем используйте локальный файл WSDL. Для этого решения необходимо создать экземпляр службы, а не использовать сгенерированный код, как это было сделано.

    Service service  = Service.create(
                        new URL(**"file:///C:/reportingService.wsdl"**), 
                        new QName("http://services.app/", "ReportingService")
                   );
    
    // ...
    
    binding.getRequestContext().put(BindingProvider.USERNAME_PROPERTY, "myuser");   
    binding.getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, "mypasswd");
    

давайте попробуем несколько вещей:

1.) Знаете ли вы, какую аутентификацию ожидает сервер?

2.) При попытке доступа https://reporting-stage.admp.mtv3.adtlgc.com/admp/ReportingService?wsdl Ты что-нибудь видишь? например, я предполагаю, что есть IP-белый список или что-то, и вы введете учетные данные там или подобное? Потому что я ничего там не вижу.

3.), Когда дело доходит до кода аутентификации защищенного веб-сервиса по протоколу HTTP таким образом:

ReportingServiceService service new ReportingServiceService();
ReportingService port = service.getReportingServicePort();
BindingProvider binding = (BindingProvider) port;

// Configure service endpoint (override defined one of the WSDL) 
BindingProvider binding = (BindingProvider) port;
binding.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, "https..");


// Add HTTP Basic Authentification credentials to this request      
binding.getRequestContext().put(BindingProvider.USERNAME_PROPERTY, "myuser");   
binding.getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, "mypasswd");
port.getCampaignRowById(14081);

установите над свойством конечной точки все, что хранится в WSDL: port вашего wsdl... часть, которую я ожидаю, будет выглядеть примерно так (и должна быть по умолчанию...):

 <wsdl:service name="ReportingServiceFoo">
    <wsdl:port binding="tns:ReportingServiceFoo" name="ReportingService">
        <soap:address location"https://myserver.com/ReportingService">
    </wsdl:port>
 </wsdl:service>

редактировать:

на

BindingProvider.ENDPOINT_ADDRESS_PROPERTY

используется для выбора цели-конечной точки во время выполнения. Поэтому, если веб-служба имеет другую конечную точку, чем в wsdl, обязательно установите ее в фактическую конечную точку таким образом.