Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/346.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java JAX-WS-添加SOAP头_Java_Web Services_Soap_Jax Ws_Ws Security - Fatal编程技术网

Java JAX-WS-添加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.

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

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());