使用 Apache CXF 实施 SOAP“网关”?

问题描述 投票:0回答:1

我有一个需要 SenderVouches 身份验证的服务,它适用于基于 CXF 的 Java 应用程序。但现在我们需要在其 SOAP/WS-Security 堆栈中集成一个不支持 SenderVouches 的基于 .NET 的应用程序。

我环顾四周,发现这篇文章解释了 SenderVouches 背后的 WS-Trust 的基本理论:https://www.xml.com/pub/a/ws/2003/06/24/ws-trust .html

在那里我找到了这张图,它可以使用 SOAP“网关”来解决我们面临的问题。 Apache CXF 是否支持实现网关部分?

我四处搜索,但大多数结果与实现 SOAP 网关无关。

soap cxf
1个回答
0
投票

结合使用 Membrane API Gateway 和 CXF 可能会有所帮助:

package com.example.wsproxy.membrane;

import com.example.wsproxy.configmodel.ServiceProperties;
import com.predic8.membrane.core.exchange.Exchange;
import com.predic8.membrane.core.http.Response;
import com.predic8.membrane.core.interceptor.AbstractInterceptor;
import com.predic8.membrane.core.interceptor.Outcome;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.apache.cxf.jaxws.DispatchImpl;

import javax.xml.soap.MessageFactory;
import javax.xml.soap.SOAPException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import javax.xml.ws.Dispatch;
import javax.xml.ws.Service;
import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;

@Slf4j
public class MembraneCxfInterceptor extends AbstractInterceptor {

    protected final Dispatch<StreamSource> dispatch;
    protected final MessageFactory messageFactory;

    public MembraneCxfInterceptor(ServiceProperties serviceProperties) throws SOAPException {
        dispatch = setupDispatch(serviceProperties);
        messageFactory = MessageFactory.newInstance();
    }

    private Dispatch<StreamSource> setupDispatch(ServiceProperties serviceProperties){

        log.debug("Setting up dispatcher for {}", serviceProperties.getServiceName());

        Service service = Service.create(serviceProperties.getWsdlLocation(), serviceProperties.getServiceName());
        Dispatch<StreamSource> d = service.createDispatch(service.getPorts().next(), StreamSource.class, Service.Mode.MESSAGE);

        log.debug("Warming up CXF...");

        // warming up CXF
        ((DispatchImpl<StreamSource>) d).getClient().getConduitSelector().getEndpoint();

        return d;
    }

    @Override
    public Outcome handleRequest(Exchange exc) throws Exception {

        StreamSource request = new StreamSource(exc.getRequest().getBodyAsStream());
        StreamSource response = dispatch.invoke(request);

        @SuppressWarnings("squid:S2095") // closed by membrane
        PipedInputStream pis = new PipedInputStream();
        @SuppressWarnings("squid:S2095") // closed in finally block
        PipedOutputStream pos = new PipedOutputStream(pis);

        new Thread(() -> {
            try {

                TransformerFactory tf = TransformerFactory.newInstance();
                Transformer t = tf.newTransformer();

                // TODO: Faults?
                t.transform(response, new StreamResult(pos));
            } catch (TransformerException e) {
                throw new CxfInterceptorTransformerException(e);
            } finally {
                try {
                    pos.close();
                } catch (IOException e) {
                    log.error("error closing piped output stream!", e);
                }
            }
        }).start();

        exc.setResponse(Response.ok().body(pis, true).build());

        return Outcome.RETURN;
    }

    static class CxfInterceptorTransformerException extends RuntimeException {
        public CxfInterceptorTransformerException(TransformerException e){
            super(e);
        }
    }
}
package com.example.wsproxy.configmodel;

import lombok.Data;

import javax.xml.namespace.QName;
import java.net.URL;

@Data
public class ServiceProperties {
    private URL wsdlLocation;
    private QName serviceName;
}
© www.soinside.com 2019 - 2024. All rights reserved.