使用 wsHttpBinding 调用 WCF Web 服务器时 Metro 客户端挂起

发布于 2024-11-30 02:10:03 字数 2335 浏览 2 评论 0原文

我已经使用 Metro 1.2 生成了一个带有本地 wsdl 的 Web 服务客户端,如下所示:

./wsimport.sh -extension -verbose -wsdllocation service.wsdl -s src -d target service.wsdl -Xendorsed

wsdl 使用 SOAP 1.2 并且wsHttpBinding。它应该连接到使用 NTLM 作为身份验证方法的 WCF 服务器。

我创建了一个Authenticator来处理NTLM身份验证:

public class NtlmAuthenticator extends Authenticator
{
    private String username = "";
    private String password = "";

    public NtlmAuthenticator(String username, String password) {
        this.username = username;
        this.password = password;
    }

    @Override
    protected PasswordAuthentication getPasswordAuthentication() {
        return new PasswordAuthentication(username, password.toCharArray());
    }
}

我在调用每个Web服务方法之前设置:

@WebEndpoint(name = "WSHttpBinding_ICustomerService")
public ICustomerService getWSHttpBindingICustomerService() {
    ICustomerService service =
        super.getPort(new QName("http://xmlns.example.com/services/Customer",
                "WSHttpBinding_ICustomerService"), ICustomerService.class);

    NtlmAuthenticator auth = new NtlmAuthenticator(username, password);  
    Authenticator.setDefault(auth);   

    return service;
}

如果我使用错误的用户名/密码,我会得到一个401 Unauthorized 返回,这很好,但是当我使用正确用户名/密码时,呼叫挂起,我从未得到响应!

请求看起来像这样(用netcat捕获它,所以主机不同,并且没有https):

POST / HTTP/1.1
Content-type: application/soap+xml;charset="utf-8";action="http://xmlns.example.com/services/ICustomerService/GetCustomer"
Password: [password]
Authorization: Basic [auth]
Username: [username]
Accept: application/soap+xml, multipart/related, text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
User-Agent: JAX-WS RI 2.1.7-b01-
Cache-Control: no-cache
Pragma: no-cache
Host: localhost:5500
Connection: keep-alive
Content-Length: 603

[xml follows]

我也尝试过wget 1.12(听说1.11有NTLM问题),但它也永远不会产生一个回应,只是等待。

[...]
---request end---
[writing POST file customerRequest.xml ... done]
HTTP request sent, awaiting response... 

我已经看到 其他人之前也遇到过这种行为,但我一直无法找出原因。有人能解释一下吗? Linux 上的 JDK 1.6。

I have generated a webservice client with a local wsdl using Metro 1.2 this way:

./wsimport.sh -extension -verbose -wsdllocation service.wsdl -s src -d target service.wsdl -Xendorsed

The wsdl uses SOAP 1.2 and wsHttpBinding. It's supposed to connect to a WCF server that's using NTLM as authentication method.

I have created an Authenticator to handle the NTLM authentication:

public class NtlmAuthenticator extends Authenticator
{
    private String username = "";
    private String password = "";

    public NtlmAuthenticator(String username, String password) {
        this.username = username;
        this.password = password;
    }

    @Override
    protected PasswordAuthentication getPasswordAuthentication() {
        return new PasswordAuthentication(username, password.toCharArray());
    }
}

Which I set before each webservice method is called:

@WebEndpoint(name = "WSHttpBinding_ICustomerService")
public ICustomerService getWSHttpBindingICustomerService() {
    ICustomerService service =
        super.getPort(new QName("http://xmlns.example.com/services/Customer",
                "WSHttpBinding_ICustomerService"), ICustomerService.class);

    NtlmAuthenticator auth = new NtlmAuthenticator(username, password);  
    Authenticator.setDefault(auth);   

    return service;
}

If I use the wrong username/password, I get a 401 Unauthorized back, which is well and all, but when I use the correct username/password, the call hangs and I never get a response!

The request looks like this (captured it with netcat, so host is different, and no https):

POST / HTTP/1.1
Content-type: application/soap+xml;charset="utf-8";action="http://xmlns.example.com/services/ICustomerService/GetCustomer"
Password: [password]
Authorization: Basic [auth]
Username: [username]
Accept: application/soap+xml, multipart/related, text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
User-Agent: JAX-WS RI 2.1.7-b01-
Cache-Control: no-cache
Pragma: no-cache
Host: localhost:5500
Connection: keep-alive
Content-Length: 603

[xml follows]

I have also tried with wget 1.12 (heard that 1.11 had problem with NTLM), but it too never yields a response, just waits.

[...]
---request end---
[writing POST file customerRequest.xml ... done]
HTTP request sent, awaiting response... 

I've seen that others have gotten this behaviour before, but I have not been able to find out why. Can anyone shed some light on this? JDK 1.6 on linux.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

∝单色的世界 2024-12-07 02:10:03

我发现我在生成的客户端代码中遗漏了一行启用Addressing并将其传递给getPort超级方法:

WebServiceFeature wsAddressing = new AddressingFeature(true);

ICustomerService service =
    super.getPort(new QName("http://xmlns.example.com/services/Customer",
            "WSHttpBinding_ICustomerService"), ICustomerService.class, 
            wsAddressing);

为什么metro没有生成这个超出了我的范围。该方法最终如下所示:

@WebEndpoint(name = "WSHttpBinding_ICustomerService")
public ICustomerService getWSHttpBindingICustomerService() {
    WebServiceFeature wsAddressing = new AddressingFeature(true);

    ICustomerService service =
        super.getPort(new QName("http://xmlns.example.com/services/Customer",
                "WSHttpBinding_ICustomerService"), ICustomerService.class, 
                wsAddressing);

    NtlmAuthenticator auth = new NtlmAuthenticator(username, password);  
    Authenticator.setDefault(auth);   

    return service;
}

这又向消息添加了 SOAP 标头:

<S:Header>
  <To xmlns="http://www.w3.org/2005/08/addressing">https://services.example.com/CustomerService.svc</To>
  <Action xmlns="http://www.w3.org/2005/08/addressing">http://xmlns.example.com/services/ICustomerService/GetCustomer</Action>
  <ReplyTo xmlns="http://www.w3.org/2005/08/addressing">
    <Address>http://www.w3.org/2005/08/addressing/anonymous</Address>
  </ReplyTo>
  <MessageID xmlns="http://www.w3.org/2005/08/addressing">uuid:d33c2888-abfa-474d-8729-95d2bcd17a96</MessageID>
</S:Header>

I found that I missed a line in my generated client code that enabled Addressing and pass it to the getPort super method:

WebServiceFeature wsAddressing = new AddressingFeature(true);

ICustomerService service =
    super.getPort(new QName("http://xmlns.example.com/services/Customer",
            "WSHttpBinding_ICustomerService"), ICustomerService.class, 
            wsAddressing);

Why metro didn't generate this is beyond me. The method looked like this in the end:

@WebEndpoint(name = "WSHttpBinding_ICustomerService")
public ICustomerService getWSHttpBindingICustomerService() {
    WebServiceFeature wsAddressing = new AddressingFeature(true);

    ICustomerService service =
        super.getPort(new QName("http://xmlns.example.com/services/Customer",
                "WSHttpBinding_ICustomerService"), ICustomerService.class, 
                wsAddressing);

    NtlmAuthenticator auth = new NtlmAuthenticator(username, password);  
    Authenticator.setDefault(auth);   

    return service;
}

This in turn added a SOAP header to the message:

<S:Header>
  <To xmlns="http://www.w3.org/2005/08/addressing">https://services.example.com/CustomerService.svc</To>
  <Action xmlns="http://www.w3.org/2005/08/addressing">http://xmlns.example.com/services/ICustomerService/GetCustomer</Action>
  <ReplyTo xmlns="http://www.w3.org/2005/08/addressing">
    <Address>http://www.w3.org/2005/08/addressing/anonymous</Address>
  </ReplyTo>
  <MessageID xmlns="http://www.w3.org/2005/08/addressing">uuid:d33c2888-abfa-474d-8729-95d2bcd17a96</MessageID>
</S:Header>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文