Java JAX WS 客户端无法进行身份验证
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/22407994/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
JAX WS client cannot authenticate
提问by Alexander Arendar
I'm trying to consume a secure (HTTPS schema) web-service with help of standard JAVA 7 JAX WS tools. This web-service requires authentication.
我试图在标准 JAVA 7 JAX WS 工具的帮助下使用安全(HTTPS 模式)Web 服务。此 Web 服务需要身份验证。
I have already successfully added certificate to my local java keystore.
All needed classes I've generated from WSDL file with help of wsimport
tool.
我已经成功地将证书添加到我的本地 java 密钥库。我在wsimport
工具的帮助下从 WSDL 文件生成了所有需要的类。
Now I am trying to use the following call to run a simple test:
现在我正在尝试使用以下调用来运行一个简单的测试:
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);
}
}
When I run the test it gives me following exception:
当我运行测试时,它给了我以下异常:
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
As you see I have tried to apply three different techniques of authentication but without any luck. Exception is the same in all three cases. What am I doing wrong?
如您所见,我尝试应用三种不同的身份验证技术,但没有任何运气。所有三种情况下的异常都是相同的。我究竟做错了什么?
P.S. if I try to access WSDL in browser the credentials I use in the code do work fine.
PS,如果我尝试在浏览器中访问 WSDL,我在代码中使用的凭据可以正常工作。
采纳答案by Loc
Your issue is not relating to SSL certificate. Your issue is relating to Authentication. Service instance need to be able to access WSDL content (before your stub invoke actual web method) but It failed, that is why you got that error.
您的问题与 SSL 证书无关。您的问题与身份验证有关。服务实例需要能够访问 WSDL 内容(在您的存根调用实际的 Web 方法之前)但它失败了,这就是您收到该错误的原因。
You have 2 solutions:
您有 2 个解决方案:
Register default Authenticator:
static { java.net.Authenticator.setDefault(new java.net.Authenticator() { @Override protected java.net.PasswordAuthentication getPasswordAuthentication() { return new java.net.PasswordAuthentication("myuser", "mypasswd".toCharArray()); } }); }
Download WSDL document and save it to LOCAL storage then use local WSDL file.For this solution, you have to create Service instance, NOT use generated code as you did.
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");
注册默认身份验证器:
static { java.net.Authenticator.setDefault(new java.net.Authenticator() { @Override protected java.net.PasswordAuthentication getPasswordAuthentication() { return new java.net.PasswordAuthentication("myuser", "mypasswd".toCharArray()); } }); }
下载 WSDL 文档并将其保存到本地存储,然后使用本地 WSDL 文件。对于此解决方案,您必须创建 Service 实例,而不是像您一样使用生成的代码。
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");
回答by JBA
Lets try a few things:
让我们尝试一些事情:
1.) Do you know what kind of Authentication the server expects?
1.) 你知道服务器需要什么样的身份验证吗?
2.) When you try to access https://reporting-stage.admp.mtv3.adtlgc.com/admp/ReportingService?wsdldo you see anything? e.g. i assume there is a IP-Whitelist or something and you will enter credentials there or similar? Because i cant see anything there.
2.) 当您尝试访问https://reporting-stage.admp.mtv3.adtlgc.com/admp/ReportingService?wsdl 时,您看到什么了吗?例如,我假设有一个 IP 白名单或其他东西,您将在那里输入凭据或类似内容?因为我在那里看不到任何东西。
3.) When it comes to the code i authenticate to a secured webservice over HTTP this way:
3.) 当涉及到代码时,我以这种方式通过 HTTP 向安全的 Web 服务进行身份验证:
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);
Set above endpoint propertie to whatever is stored in your wsdl's wsdl:port... part which i expect to look something like this (and should be the default...):
将上面的端点属性设置为存储在 wsdl 的 wsdl:port... 部分中的任何内容,我希望它看起来像这样(并且应该是默认值...):
<wsdl:service name="ReportingServiceFoo">
<wsdl:port binding="tns:ReportingServiceFoo" name="ReportingService">
<soap:address location"https://myserver.com/ReportingService">
</wsdl:port>
</wsdl:service>
Edit:
编辑:
The
这
BindingProvider.ENDPOINT_ADDRESS_PROPERTY
is used to set the target-endpoint at runtime. So if the webservice has a different endpoint than the one in the wsdl make sure to set it to the actual endpoint this way.
用于在运行时设置目标端点。因此,如果 Web 服务的端点与 wsdl 中的端点不同,请确保以这种方式将其设置为实际端点。