JAX-WS - 添加 SOAP 标头

问题描述:

我正在尝试创建一个独立的客户端来使用一些 Web 服务.我必须将我的用户名和密码添加到 SOAP 标头中.我尝试按如下方式添加凭据:

I am trying to create a standalone client to consume some web services. I must add my username and password to the SOAP Header. I tried adding the credentials as follows:

OTSWebSvcsService service = new OTSWebSvcsService();
OTSWebSvcs port = service.getOTSWebSvcs();

BindingProvider prov = (BindingProvider)port;
prov.getRequestContext().put(BindingProvider.USERNAME_PROPERTY, "myusername");
prov.getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, "mypassword");

...

当我在服务上调用方法时,出现以下异常:

When I call a method on the service I get the following exception:

com.ibm.wsspi.wssecurity.SoapSecurityException: WSEC5048E: One of "SOAP Header" elements required.

我做错了什么?我将如何将这些属性添加到 SOAP 标头?

What am I doing wrong? How would I add these properties to the SOAP Header?

已我使用的是 JDK6 中包含的 JAX-WS 2.1.我现在使用 JAX-WS 2.2.我现在收到以下异常:

Edited: I was using JAX-WS 2.1 included in JDK6. I am now using JAX-WS 2.2. I now get the following exception:

com.ibm.wsspi.wssecurity.SoapSecurityException: WSEC5509E: A security token whose type is [http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#UsernameToken] is required.

如何创建此令牌?

不是 100% 确定,因为问题缺少一些细节,但如果您使用的是 JAX-WS RI,请查看 发送请求时添加SOAP头:

Not 100% sure as the question is missing some details but if you are using JAX-WS RI, then have a look at Adding SOAP headers when sending requests:

这样做的便携方式是你创建了一个 SOAPHandler 并且一团糟与 SAAJ,但 RI 提供了一个这样做的更好方法.

The portable way of doing this is that you create a SOAPHandler and mess with SAAJ, but the RI provides a better way of doing this.

当您创建代理或分派时对象,他们实现BindingProvider 接口.当你使用 JAX-WS RI,您可以向下转型WSBindingProvider 定义了一个仅由JAX-WS RI.

When you create a proxy or dispatch object, they implement BindingProvider interface. When you use the JAX-WS RI, you can downcast to WSBindingProvider which defines a few more methods provided only by the JAX-WS RI.

这个界面让你设置一个任意数量的 Header 对象,每个代表一个 SOAP 标头.你如果你可以自己实现它想要,但很可能你会使用其中之一定义的工厂方法Headers 类来创建一个.

This interface lets you set an arbitrary number of Header object, each representing a SOAP header. You can implement it on your own if you want, but most likely you'd use one of the factory methods defined on Headers class to create one.

import com.sun.xml.ws.developer.WSBindingProvider;

HelloPort port = helloService.getHelloPort();  // or something like that...
WSBindingProvider bp = (WSBindingProvider)port;

bp.setOutboundHeader(
  // simple string value as a header, like <simpleHeader>stringValue</simpleHeader>
  Headers.create(new QName("simpleHeader"),"stringValue"),
  // create a header from JAXB object
  Headers.create(jaxbContext,myJaxbObject)
);

相应地更新您的代码,然后重试.如果您没有使用 JAX-WS RI,请更新您的问题并提供更多上下文信息.

Update your code accordingly and try again. And if you're not using JAX-WS RI, please update your question and provide more context information.

更新:您要调用的 Web 服务似乎已使用 WS-Security/UsernameTokens 进行保护.这与您最初的问题有点不同.无论如何,要配置您的客户端以发送用户名和密码,我建议查看很棒的帖子 为基于 Metro 的 Web 服务实施 WS-Security UsernameToken Profile(跳到第 4 步).在这一步使用 NetBeans 可能会减轻很多事情.

Update: It appears that the web service you want to call is secured with WS-Security/UsernameTokens. This is a bit different from your initial question. Anyway, to configure your client to send usernames and passwords, I suggest to check the great post Implementing the WS-Security UsernameToken Profile for Metro-based web services (jump to step 4). Using NetBeans for this step might ease things a lot.