【问题标题】:How can I add namespace declarations in a SOAPEnvelope如何在 SOAPEnvelope 中添加命名空间声明
【发布时间】:2015-07-02 09:47:03
【问题描述】:

在我的肥皂应用程序中,我使用的是 apache cxf。

这是我的代码,它将向服务器提交数据。

import org.apache.cxf.Bus;
import org.apache.cxf.BusFactory;
import org.apache.cxf.bus.spring.SpringBusFactory;
import org.apache.cxf.endpoint.Client;
import org.apache.cxf.frontend.ClientProxy;
import org.apache.cxf.interceptor.LoggingInInterceptor;
import org.apache.cxf.interceptor.LoggingOutInterceptor;
import org.apache.cxf.ws.security.wss4j.DefaultCryptoCoverageChecker;
import org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor;
import org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor;

SpringBusFactory bf = new SpringBusFactory();
URL              busFile = Submission.class.getResource(WSSEC_XML);    
File             f = new File(busFile.getPath());

Bus              bus = bf.createBus(busFile.toString());
BusFactory.setDefaultBus(bus);
BusFactory.setThreadDefaultBus(bus);

DefaultCryptoCoverageChecker coverageChecker = new DefaultCryptoCoverageChecker();

coverageChecker.setSignBody(true);
coverageChecker.setSignTimestamp(true);
coverageChecker.setEncryptBody(true);
coverageChecker.setSignAddressingHeaders(true);

MyClaimservice  service = new MyClaimservice();
Myclaims        port = service.getMyClaimsSoap11();
BindingProvider provider = (BindingProvider) port;
provider.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, ENDPOINT_ADDRESS);
provider.getRequestContext().put(BindingProvider.SOAPACTION_URI_PROPERTY, SOAP_ACTION);

Client client = ClientProxy.getClient(port);

client.getOutInterceptors().add(new LoggingOutInterceptor());
client.getInInterceptors().add(new LoggingInInterceptor());
client.getInInterceptors().add(new WSS4JInInterceptor(getInProps()));
client.getOutInterceptors().add(new WSS4JOutInterceptor(getOutProps()));
client.getInInterceptors().add(coverageChecker);

SubmissionResponse response = port.submission(request);

我的请求数据是这样形成的。

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
    ....
    ....
    ....
</soap:Envelope>

我需要向&lt;soap:Envelope&gt; 添加额外的命名空间。我预期的数据应该是这样的,

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:prefix1="url1" xmlns:prefix2="url2" xmlns:prefix3:"url3">
    ....
    ....
    ....
</soap:Envelope>

我尝试使用 Map 和 XpathExpressions 将这些前缀和命名空间 URL 添加到 DefaultCryptoCoverageChecker。但似乎它没有对我的请求数据进行任何更改。

Map<String, String> prefixes = new HashMap<String, String>();

prefixes.put("prefix1", "url1");
prefixes.put("prefix2", "url2");
prefixes.put("prefix3", "url3");
prefixes.put("prefix4", "url4");
prefixes.put("prefix5", "url5");

List<XPathExpression> xpaths = Arrays.asList(
        new XPathExpression("//prefix1:Envelope", CoverageType.SIGNED),
        new XPathExpression("//prefix2:Envelope", CoverageType.SIGNED),
        new XPathExpression("//prefix3:Envelope", CoverageType.SIGNED),
        new XPathExpression("//prefix4:Envelope", CoverageType.SIGNED),
        new XPathExpression("//prefix5:Envelope", CoverageType.SIGNED));

DefaultCryptoCoverageChecker coverageChecker = new DefaultCryptoCoverageChecker();

coverageChecker.addPrefixes(prefixes);
coverageChecker.addXPaths(xpaths);

coverageChecker.setSignBody(true);
coverageChecker.setSignTimestamp(true);
coverageChecker.setEncryptBody(true);
coverageChecker.setSignAddressingHeaders(true);

任何帮助将不胜感激。

更新 2:

我已经尝试过 Apache cxf 的转换功能。

Map<String, String> outTransformMap = Collections.singletonMap("{http://schemas.xmlsoap.org/soap/envelope/}Envelope", "Envelope");
TransformOutInterceptor transformOutInterceptor = new TransformOutInterceptor();
transformOutInterceptor.setOutTransformElements(outTransformMap);
client.getOutInterceptors().add(transformOutInterceptor);

根据http://cxf.apache.org/docs/transformationfeature.html#TransformationFeature-JAX-WS,上述代码将从Envelope 节点中删除该特定命名空间。我还可以通过看到 xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/ 正在从 &lt;soap:Envelope&gt; 中删除来确认它

我尝试了 transformOutInterceptor.setOutTransformElements(outTransformMap); 的反向操作,将其替换为 transformOutInterceptor.setOutAppendElements(outTransformMap);,其中 outTransformMap 现在将包含 Collections.singletonMap("{url1 (which I need to add)}Envelope", "Envelope");。但它不会将其作为新的命名空间附加到Envelope。我在这里做错了什么.. 除了默认命名空间之外,向&lt;soap:Envelope&gt; 添加额外的命名空间真的很难吗?

【问题讨论】:

    标签: java web-services soap cxf ws-security


    【解决方案1】:

    在cxf论坛上挖掘后,我找到了答案。

    Map<String, String> nsMap = new HashMap<>();
    
    nsMap.put("prefix1", "url1");
    nsMap.put("prefix2", "url2");
    nsMap.put("prefix3", "url3");
    nsMap.put("prefix4", "url4");
    nsMap.put("prefix5", "http://www.w3.org/2001/04/xmlenc#");
    
    Client client = ClientProxy.getClient(port);   
    client.getRequestContext().put("soap.env.ns.map", nsMap);
    

    如果有人知道如何为 &lt;soap:Header&gt; 做同样的事情,我将不胜感激

    【讨论】:

    • 谢谢兄弟...这个非常有用。你能对
      做同样的事情吗?
    【解决方案2】:

    您可以像这样添加标题:

    UserCredentials authHeader = new UserCredentials();
        authHeader.setUsername(username);
        authHeader.setPassword(password);
        ArrayList<Header> headers = new ArrayList<Header>(1);
        try {
            Header soapHeader = new Header(new QName(TQIntegrationV2.TQIntegrationV2Soap.getNamespaceURI(), "UserCredentials"), authHeader, new JAXBDataBinding(UserCredentials.class));
            headers.add(soapHeader);
        } catch (JAXBException ex) {
            LOGGER.error("Exception trying to serialize header: {}", ex);
        }
        client.getRequestContext().put(Header.HEADER_LIST, headers);
    

    如果你不想,你可以离开 setUsername/setPassword。

    【讨论】:

    • 很高兴我能帮忙找到答案。
    • 在我的 SOAP UI 中,envelope and Header 形成为 &lt;soapenv:Envelope and &lt;soapenv:Header,而“To From Action ReplyTo”形成为 &lt;wsa:To , &lt;wsa:From , &lt;wsa:Action , &lt;wsa:ReplyTo。但在我的 java 请求中,它形成为&lt;soap:Envelope and &lt;soap:Header(在soap 之后没有env)和&lt;To , &lt;From , &lt;Action , &lt;ReplyTo(在节点之前没有wsa:)。无论如何我可以更改节点前缀以匹配 SOAPUI 数据?
    猜你喜欢
    • 1970-01-01
    • 2018-02-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-27
    • 1970-01-01
    • 2012-08-16
    相关资源
    最近更新 更多