Java JAX-WS-添加SOAP头
我正在尝试创建一个独立的客户端来使用一些web服务。我必须将我的用户名和密码添加到SOAP头中。我尝试按如下方式添加凭据:Java JAX-WS-添加SOAP头,java,web-services,soap,jax-ws,ws-security,Java,Web Services,Soap,Jax Ws,Ws Security,我正在尝试创建一个独立的客户端来使用一些web服务。我必须将我的用户名和密码添加到SOAP头中。我尝试按如下方式添加凭据: OTSWebSvcsService service = new OTSWebSvcsService(); OTSWebSvcs port = service.getOTSWebSvcs(); BindingProvider prov = (BindingProvider)port; prov.getRequestContext().put(BindingProvider.
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");
...
当我调用服务上的方法时,会出现以下异常:
com.ibm.wsspi.wssecurity.SoapSecurityException: WSEC5048E: One of "SOAP Header" elements required.
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.
我做错了什么?如何将这些属性添加到SOAP头中
编辑:我使用的是JDK6中包含的JAX-WS2.1。我现在使用的是JAX-WS2.2。我现在得到以下异常:
com.ibm.wsspi.wssecurity.SoapSecurityException: WSEC5048E: One of "SOAP Header" elements required.
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,请查看: 便携式的方法是 您创建了一个
SOAPHandler
和一个mess
与SAAJ合作,但国际扶轮提供
更好的方法
创建代理或分派时
对象,它们实现
BindingProvider
接口。当你
使用JAX-WSRI,您可以向下转换到
WSBindingProvider
定义
只有
JAX-WSRI
此界面允许您设置
任意数量的头对象,
每个代表一个SOAP头。你
如果您愿意,您可以自己实现它
想要,但很可能你会使用
上定义的工厂方法
标题
类创建一个标题
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)
);
导入com.sun.xml.ws.developer.WSBindingProvider;
HelloPort端口=helloService.getHelloPort();//或者类似的事情。。。
WSBindingProvider bp=(WSBindingProvider)端口;
bp.setOutboundHeader(
//作为标题的简单字符串值,如stringValue
创建(新的QName(“simpleHeader”),“stringValue”),
//从JAXB对象创建头
create(jaxbContext、myJaxbObject)
);
请相应地更新代码,然后重试。如果您没有使用JAX-WSRI,请更新您的问题并提供更多上下文信息
更新:您要调用的web服务似乎由WS-Security/UsernameToken保护。这和你最初的问题有点不同。无论如何,要将客户端配置为发送用户名和密码,我建议您查看这篇文章(跳到第4步)。在这一步中使用NetBeans可能会大大简化工作。此外,如果使用Maven构建项目,则需要添加以下依赖项:
<dependency>
<groupId>com.sun.xml.ws</groupId>
<artifactId>jaxws-rt</artifactId>
<version>{currentversion}/version>
</dependency>
com.sun.xml.ws
可以使用@WebParam(header=true)在SOAP头(JaxWS)中传输数据:
如果要生成具有SOAP头的客户端,则需要使用-XadditionalHeaders:
wsimport -keep -Xnocompile -XadditionalHeaders -Xdebug http://12.34.56.78:8080/TestHeaders/somewsdl?wsdl -d /home/evgeny/DEVELOPMENT/JAVA/gen
如果不需要@Oneway web服务,您可以使用Holder:
@WebMethod(operationName = "SendRequest", action = "http://abcd.ru/")
public void sendRequest(
@WebParam(name = "Message", targetNamespace = "http://abcd.ru/", partName = "Message")
Data message,
@WebParam(name = "ServiceHeader", targetNamespace = "http://abcd.ru/", header = true, partName = "ServiceHeader")
Holder<Header> serviceHeader);
@WebMethod(operationName=“SendRequest”,操作=”http://abcd.ru/")
公共无效发送请求(
@WebParam(name=“Message”,targetNamespace=”http://abcd.ru/“,partName=“Message”)
数据电文,
@WebParam(name=“ServiceHeader”,targetNamespace=”http://abcd.ru/,header=true,partName=“ServiceHeader”)
持有人(报头);
使用maven和插件。这将生成一个web服务客户端。请确保将设置为true。这将生成带有标题输入的方法。我之所以添加此答案,是因为其他答案都不适合我
我必须向代理添加标题处理程序:
import java.util.Set;
import java.util.TreeSet;
import javax.xml.namespace.QName;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPFactory;
import javax.xml.soap.SOAPHeader;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;
public class SOAPHeaderHandler implements SOAPHandler<SOAPMessageContext> {
private final String authenticatedToken;
public SOAPHeaderHandler(String authenticatedToken) {
this.authenticatedToken = authenticatedToken;
}
public boolean handleMessage(SOAPMessageContext context) {
Boolean outboundProperty =
(Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
if (outboundProperty.booleanValue()) {
try {
SOAPEnvelope envelope = context.getMessage().getSOAPPart().getEnvelope();
SOAPFactory factory = SOAPFactory.newInstance();
String prefix = "urn";
String uri = "urn:xxxx";
SOAPElement securityElem =
factory.createElement("Element", prefix, uri);
SOAPElement tokenElem =
factory.createElement("Element2", prefix, uri);
tokenElem.addTextNode(authenticatedToken);
securityElem.addChildElement(tokenElem);
SOAPHeader header = envelope.addHeader();
header.addChildElement(securityElem);
} catch (Exception e) {
e.printStackTrace();
}
} else {
// inbound
}
return true;
}
public Set<QName> getHeaders() {
return new TreeSet();
}
public boolean handleFault(SOAPMessageContext context) {
return false;
}
public void close(MessageContext context) {
//
}
}
在jaxws-rt-2.2.10-ources.jar中\com\sun\xml\ws\transport\http\client\HttpTransportPipe.java
:
public Packet process(Packet request) {
Map<String, List<String>> userHeaders = (Map<String, List<String>>) request.invocationProperties.get(MessageContext.HTTP_REQUEST_HEADERS);
if (userHeaders != null) {
reqHeaders.putAll(userHeaders);
公共数据包处理(数据包请求){
Map userHeaders=(Map)request.invocationProperties.get(MessageContext.HTTP\u request\u HEADERS);
if(userHeaders!=null){
reqHeaders.putAll(userHeaders);
因此,使用键MessageContext.HTTP\u REQUEST\u HEADERS
将requestContext中的Map
复制到SOAP头中。
样品
BindingProvider.USERNAME\u属性
和BindingProvider.PASSWORD\u属性
密钥在HttpTransportPipe.addBasicAuth()
中以特殊方式处理,添加标准基本授权授权
头
另请参见您可以将用户名和密码添加到SOAP头中
BindingProvider prov = (BindingProvider)port;
prov.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY,
"your end point"));
Map<String, List<String>> headers = new HashMap<String, List<String>>();
prov.getRequestContext().put(BindingProvider.USERNAME_PROPERTY, "myusername");
prov.getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, "mypassword");
prov.getRequestContext().put(MessageContext.HTTP_REQUEST_HEADERS, headers);
BindingProvider prov=(BindingProvider)端口;
prov.getRequestContext().put(BindingProvider.ENDPOINT\u ADDRESS\u属性,
“你的终点”);
Map headers=newhashmap();
prov.getRequestContext().put(BindingProvider.USERNAME_属性,“myusername”);
prov.getRequestContext().put(BindingProvider.PASSWORD_属性,“mypassword”);
prov.getRequestContext().put(MessageContext.HTTP_请求_头,头);
我在这里挣扎着寻找所有答案,首先是,由于Java编译器不再默认绑定rt.jar
(并且使用内部类使其特定于运行时实现),这变得越来越困难
让我靠近了。处理程序在最后一段代码中的连接方式对我不起作用,但从未调用过
我最终使用了他的handler类的变体,但将其连接到javax.xml.ws.Service
实例中,如下所示:
jaxbContext = (JAXBRIContext) JAXBContext.newInstance(CabeceraCR.class.getPackage().getName());
Service=Service.create(url,qname);
service.setHandlerResolver(
portInfo->Collections.singletonList(新的SOAPHeaderHandler(handlerArgs))
);
最好的选择(当然对我来说)是自己动手。这意味着您可以通过编程修改SOAP消息的所有部分
Binding binding = prov.getBinding();
List<Handler> handlerChain = binding.getHandlerChain();
handlerChain.add( new ModifyMessageHandler() );
binding.setHandlerChain( handlerChain );
我希望这有助于您将对象添加到标题中我们使用这里使用的示例,但我将完成
ObjectFactory objectFactory = new ObjectFactory();
CabeceraCR cabeceraCR =objectFactory.createCabeceraCR();
cabeceraCR.setUsuario("xxxxx");
cabeceraCR.setClave("xxxxx");
通过对象工厂,我们创建了被要求传递到头上的对象
WSBindingProvider bp = (WSBindingProvider)wsXXXXXXSoap;
bp.setOutboundHeaders(
// Sets a simple string value as a header
Headers.create(jaxbContext,objectFactory.createCabeceraCR(cabeceraCR))
);
我们使用WSBindingProvider添加标头。如果直接使用该对象,则会出现一些错误,因此我们使用该方法
objectFactory.createCabeceraCR(cabeceraCR)
此方法将在对象工厂上创建类似的JAXBElement
@XmlElementDecl(namespace = "http://www.creditreport.ec/", name = "CabeceraCR")
public JAXBElement<CabeceraCR> createCabeceraCR(CabeceraCR value) {
return new JAXBElement<CabeceraCR>(_CabeceraCR_QNAME, CabeceraCR.class, null, value);
}
这将把对象添加到标题中。+1,在本例中,-xaadditionalHeaders
是一个重要属性。header=true
jaxbContext = (JAXBRIContext) JAXBContext.newInstance(CabeceraCR.class.getPackage().getName());