如何连接到Apache Tomcat上托管的Apache Cxf Web服务(启用Ws安全性)?

wwtsj6pe  于 2022-11-16  发布在  Apache
关注(0)|答案(2)|浏览(160)

我在apacheCxf jar中使用了ws安全示例中的wssec_sign_enc示例,该示例部署在apache tomcat 7.0.29下。我的web.xml是:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
  <display-name>TestingWebWsSecurity</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>

  </welcome-file-list>
  <servlet>
    <description>Apache CXF Endpoint</description>
    <display-name>cxf</display-name>
    <servlet-name>cxf</servlet-name>
    <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>cxf</servlet-name>
    <url-pattern>/services/*</url-pattern>
  </servlet-mapping>
  <session-config>
    <session-timeout>60</session-timeout>
  </session-config>
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>WEB-INF/cxf-beans.xml</param-value>
  </context-param>
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
   </web-app>

我的cxf-beans.xml是

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws"
    xmlns:cxf="http://cxf.apache.org/core" xmlns:wsa="http://cxf.apache.org/ws/addressing"
    xmlns:http="http://cxf.apache.org/transports/http/configuration"
    xmlns:wsrm-policy="http://schemas.xmlsoap.org/ws/2005/02/rm/policy"
    xmlns:wsrm-mgr="http://cxf.apache.org/ws/rm/manager"
    xsi:schemaLocation="        http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd        http://cxf.apache.org/transports/http/configuration http://cxf.apache.org/schemas/configuration/http-conf.xsd        http://schemas.xmlsoap.org/ws/2005/02/rm/policy http://schemas.xmlsoap.org/ws/2005/02/rm/wsrm-policy.xsd        http://cxf.apache.org/ws/rm/manager http://cxf.apache.org/schemas/configuration/wsrm-manager.xsd        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd     http://cxf.apache.org/jaxws     http://cxf.apache.org/schemas/jaxws.xsd ">
    <import resource="classpath:META-INF/cxf/cxf.xml" />
    <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
    <import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
    <import resource="classpath:META-INF/cxf/cxf.xml" />
    <import resource="classpath*:META-INF/cxf/cxf-extension-*.xml" />

    <cxf:bus>
        <cxf:features>
            <cxf:logging />
            <wsa:addressing />
        </cxf:features>
    </cxf:bus>

    <http:conduit
        name="{http://cxf.apache.org/hello_world_soap_http}GreeterPort.http-conduit">
        <http:client DecoupledEndpoint="http://localhost:12000/decoupled_endpoint" />
    </http:conduit>

    <jaxws:endpoint xmlns:tns="http://cxf.apache.org/hello_world_soap_http"
        id="greeter" implementor="org.apache.cxf.hello_world_soap_http.GreeterImpl"
        wsdlLocation="wsdl/hello_world_wssec.wsdl" endpointName="tns:GreeterPort"
        serviceName="tns:GreeterService" address="/GreeterPort">
        <jaxws:features>
            <bean class="org.apache.cxf.feature.LoggingFeature" />
        </jaxws:features>
        <jaxws:outInterceptors>
            <bean class="org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor">
                <constructor-arg>
                    <map>
                        <entry key="action" value="UsernameToken Timestamp Signature Encrypt" />
                        <entry key="passwordType" value="PasswordText" />
                        <entry key="passwordCallbackClass" value="demo.wssec.server.UTPasswordCallback" />
                        <entry key="user" value="Alice" />
                        <entry key="signatureUser" value="serverx509v1" />
                        <entry key="encryptionUser" value="clientx509v1" />
                        <entry key="encryptionPropFile" value="etc/Server_SignVerf.properties" />
                        <entry key="encryptionKeyIdentifier" value="IssuerSerial" />
                        <entry key="encryptionParts"
                            value="{Element}{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd}Timestamp;{Content}{http://schemas.xmlsoap.org/soap/envelope/}Body" />
                        <entry key="signaturePropFile" value="etc/Server_Decrypt.properties" />
                        <entry key="signatureParts"
                            value="{Element}{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd}Timestamp;{Element}{http://schemas.xmlsoap.org/soap/envelope/}Body" />
                        <entry key="signatureKeyIdentifier" value="DirectReference" />

                        <entry key="encryptionKeyTransportAlgorithm" value="http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p" />
                        <entry key="signatureAlgorithm" value="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
                    </map>
                </constructor-arg>
            </bean>
        </jaxws:outInterceptors>
        <jaxws:inInterceptors>
            <bean class="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor">
                <constructor-arg>
                    <map>
                        <entry key="action" value="UsernameToken Timestamp Signature Encrypt" />
                        <entry key="passwordType" value="PasswordDigest" />
                        <entry key="passwordCallbackClass" value="demo.wssec.server.UTPasswordCallback" />
                        <!-- <entry key="user" value="server" /> -->
                        <entry key="decryptionPropFile" value="etc/Server_Decrypt.properties" />
                        <entry key="encryptionKeyIdentifier" value="IssuerSerial" />

                        <entry key="signaturePropFile" value="etc/Server_SignVerf.properties" />
                        <entry key="signatureKeyIdentifier" value="DirectReference" />

                        <entry key="encryptionKeyTransportAlgorithm" value="http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p" />
                        <entry key="signatureAlgorithm" value="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
                    </map>
                </constructor-arg>
            </bean>
        </jaxws:inInterceptors>
    </jaxws:endpoint>

</beans>

我的wsdl文件是:

<?xml version="1.0" encoding="UTF-8"?>

<wsdl:definitions name="HelloWorld" targetNamespace="http://cxf.apache.org/hello_world_soap_http" 
    xmlns="http://schemas.xmlsoap.org/wsdl/" 
    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" 
    xmlns:tns="http://cxf.apache.org/hello_world_soap_http"
    xmlns:x1="http://cxf.apache.org/hello_world_soap_http/types"
    xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <wsdl:types>
        <schema targetNamespace="http://cxf.apache.org/hello_world_soap_http/types" 
            xmlns="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
            <element name="sayHi">
                <complexType/>
            </element>
            <element name="sayHiResponse">
                <complexType>
                    <sequence>
                        <element name="responseType" type="xsd:string"/>
                    </sequence>
                </complexType>
            </element>
            <element name="greetMe">
                <complexType>
                    <sequence>
                        <element name="requestType" type="xsd:string"/>
                    </sequence>
                </complexType>
            </element>
            <element name="greetMeResponse">
                <complexType>
                    <sequence>
                        <element name="responseType" type="xsd:string"/>
                    </sequence>
                </complexType>
            </element>
            <element name="greetMeOneWay">
                <complexType>
                    <sequence>
                        <element name="requestType" type="xsd:string"/>
                    </sequence>
                </complexType>
            </element>
        </schema>
    </wsdl:types>

    <wsdl:message name="sayHiRequest">
        <wsdl:part element="x1:sayHi" name="in"/>
    </wsdl:message>
    <wsdl:message name="sayHiResponse">
        <wsdl:part element="x1:sayHiResponse" name="out"/>
    </wsdl:message>
    <wsdl:message name="greetMeRequest">
        <wsdl:part element="x1:greetMe" name="in"/>
    </wsdl:message>
    <wsdl:message name="greetMeResponse">
        <wsdl:part element="x1:greetMeResponse" name="out"/>
    </wsdl:message>
    <wsdl:message name="greetMeOneWayRequest">
        <wsdl:part element="x1:greetMeOneWay" name="in"/>
    </wsdl:message>

    <wsdl:portType name="Greeter">
        <wsdl:operation name="sayHi">
            <wsdl:input message="tns:sayHiRequest" name="sayHiRequest"/>
            <wsdl:output message="tns:sayHiResponse" name="sayHiResponse"/>
        </wsdl:operation>

        <wsdl:operation name="greetMe">
            <wsdl:input message="tns:greetMeRequest" name="greetMeRequest"/>
            <wsdl:output message="tns:greetMeResponse" name="greetMeResponse"/>
        </wsdl:operation>

        <wsdl:operation name="greetMeOneWay">
            <wsdl:input message="tns:greetMeOneWayRequest" name="greetMeOneWayRequest"/>
        </wsdl:operation>

    </wsdl:portType>

    <wsdl:binding name="Greeter_SOAPBinding" type="tns:Greeter">
        <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>

        <wsdl:operation name="sayHi">
            <soap:operation soapAction="" style="document"/>
            <wsdl:input name="sayHiRequest">
                <soap:body use="literal"/>
            </wsdl:input>
            <wsdl:output name="sayHiResponse">
                <soap:body use="literal"/>
            </wsdl:output>
        </wsdl:operation>

        <wsdl:operation name="greetMe">
            <soap:operation soapAction="" style="document"/>
            <wsdl:input name="greetMeRequest">
                <soap:body use="literal"/>
            </wsdl:input>
            <wsdl:output name="greetMeResponse">
                <soap:body use="literal"/>
            </wsdl:output>
        </wsdl:operation>

        <wsdl:operation name="greetMeOneWay">
            <soap:operation soapAction="" style="document"/>
            <wsdl:input name="greetMeOneWayRequest">
                <soap:body use="literal"/>
            </wsdl:input>
        </wsdl:operation>
    </wsdl:binding>

    <wsdl:service name="GreeterService">
        <wsdl:port binding="tns:Greeter_SOAPBinding" name="GreeterPort">
            <soap:address location="http://localhost:12000/TestingWebWsSecurity/services/GreeterPort"/>
            <wswa:UsingAddressing xmlns:wswa="http://www.w3.org/2005/02/addressing/wsdl"/>
        </wsdl:port>
    </wsdl:service>
</wsdl:definitions>

客户端代码为:

package demo.wssec.client;

import java.io.Closeable;

import java.lang.reflect.UndeclaredThrowableException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

import org.apache.cxf.Bus;
import org.apache.cxf.BusFactory;
import org.apache.cxf.bus.spring.SpringBusFactory;
import org.apache.cxf.hello_world_soap_http.Greeter;
import org.apache.cxf.hello_world_soap_http.GreeterService;

import org.apache.cxf.ws.security.wss4j.DefaultCryptoCoverageChecker;
import org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor;
import org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor;

public final class Client {

    private static final String WSU_NS
        = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd";

    private Client() {
    }

    public static void main(String args[]) throws Exception {
        try {

            SpringBusFactory bf = new SpringBusFactory();
            URL busFile = Client.class.getResource("wssec.xml");
            Bus bus = bf.createBus(busFile.toString());
            BusFactory.setDefaultBus(bus);

            Map<String, Object> outProps = new HashMap<String, Object>();
            outProps.put("action", "UsernameToken Timestamp Signature Encrypt");

            outProps.put("passwordType", "PasswordDigest");

            outProps.put("user", "abcd");
            outProps.put("password", "storepassword");
            outProps.put("signatureUser", "clientx509v1");

            outProps.put("passwordCallbackClass", "demo.wssec.client.UTPasswordCallback");

            outProps.put("encryptionUser", "serverx509v1");
            outProps.put("encryptionPropFile", "etc/Client_Encrypt.properties");
            outProps.put("encryptionKeyIdentifier", "IssuerSerial");
            outProps.put("encryptionParts",
                         "{Element}{" + WSU_NS + "}Timestamp;"
                         + "{Content}{http://schemas.xmlsoap.org/soap/envelope/}Body");

            outProps.put("signaturePropFile", "etc/Client_Sign.properties");
            outProps.put("signatureKeyIdentifier", "DirectReference");
            outProps.put("signatureParts",
                         "{Element}{" + WSU_NS + "}Timestamp;"
                         + "{Element}{http://schemas.xmlsoap.org/soap/envelope/}Body;"
                         + "{}{http://www.w3.org/2005/08/addressing}ReplyTo;");

            outProps.put("encryptionKeyTransportAlgorithm", 
                         "http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p");
            outProps.put("signatureAlgorithm", "http://www.w3.org/2000/09/xmldsig#rsa-sha1");

            bus.getOutInterceptors().add(new WSS4JOutInterceptor(outProps));

            Map<String, Object> inProps = new HashMap<String, Object>();

            inProps.put("action", "UsernameToken Timestamp Signature Encrypt");
            inProps.put("passwordType", "PasswordText");
            inProps.put("passwordCallbackClass", "demo.wssec.client.UTPasswordCallback");

            inProps.put("decryptionPropFile", "etc/Client_Sign.properties");
            inProps.put("encryptionKeyIdentifier", "IssuerSerial");

            inProps.put("signaturePropFile", "etc/Client_Encrypt.properties");
            inProps.put("signatureKeyIdentifier", "DirectReference");

            inProps.put("encryptionKeyTransportAlgorithm", 
                         "http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p");
            inProps.put("signatureAlgorithm", "http://www.w3.org/2000/09/xmldsig#rsa-sha1");

            bus.getInInterceptors().add(new WSS4JInInterceptor(inProps));

            // Check to make sure that the SOAP Body and Timestamp were signed,
            // and that the SOAP Body was encrypted
            DefaultCryptoCoverageChecker coverageChecker = new DefaultCryptoCoverageChecker();
            coverageChecker.setSignBody(true);
            coverageChecker.setSignTimestamp(true);
            coverageChecker.setEncryptBody(true);
            bus.getInInterceptors().add(coverageChecker);

            GreeterService service = new GreeterService();
            Greeter port = service.getGreeterPort();

            String[] names = new String[] {"Anne", "Bill", "Chris", "Sachin Tendulkar"};
            // make a sequence of 4 invocations
            for (int i = 0; i < 4; i++) {
                System.out.println("Invoking greetMe...");
                String response = port.greetMe(names[i]);
                System.out.println("response: " + response + "\n");
            }

            // allow asynchronous resends to occur
            Thread.sleep(30 * 1000);

            if (port instanceof Closeable) {
                ((Closeable)port).close();
            }

            bus.shutdown(true);

        } catch (UndeclaredThrowableException ex) {
            ex.getUndeclaredThrowable().printStackTrace();
        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            System.exit(0);
        }
    }
}

当我执行客户端代码时,它说:

Caused by: org.apache.cxf.transport.http.HTTPException: HTTP response '404: Not Found' when communicating with http://localhost:12000/TestingWebWsSecurity/services/GreeterPort
    at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponseInternal(HTTPConduit.java:1526)
    at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponse(HTTPConduit.java:1486)
    at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.close(HTTPConduit.java:1305)
    at org.apache.cxf.io.CacheAndWriteOutputStream.postClose(CacheAndWriteOutputStream.java:50)
    at org.apache.cxf.io.CachedOutputStream.close(CachedOutputStream.java:223)
    at org.apache.cxf.transport.AbstractConduit.close(AbstractConduit.java:56)
    at org.apache.cxf.transport.http.HTTPConduit.close(HTTPConduit.java:623)
    at org.apache.cxf.interceptor.MessageSenderInterceptor$MessageSenderEndingInterceptor.handleMessage(MessageSenderInterceptor.java:62)
    ... 9 more

javax.xml.ws.WebServiceException: Could not send Message.
    at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:145)
    at com.sun.proxy.$Proxy40.greetMe(Unknown Source)
    at demo.wssec.client.Client.main(Client.java:120)
Caused by: org.apache.cxf.transport.http.HTTPException: HTTP response '404: Not Found' when communicating with http://localhost:12000/TestingWebWsSecurity/services/GreeterPort
    at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponseInternal(HTTPConduit.java:1526)
    at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponse(HTTPConduit.java:1486)
    at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.close(HTTPConduit.java:1305)
    at org.apache.cxf.io.CacheAndWriteOutputStream.postClose(CacheAndWriteOutputStream.java:50)
    at org.apache.cxf.io.CachedOutputStream.close(CachedOutputStream.java:223)
    at org.apache.cxf.transport.AbstractConduit.close(AbstractConduit.java:56)
    at org.apache.cxf.transport.http.HTTPConduit.close(HTTPConduit.java:623)
    at org.apache.cxf.interceptor.MessageSenderInterceptor$MessageSenderEndingInterceptor.handleMessage(MessageSenderInterceptor.java:62)
    at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:271)
    at org.apache.cxf.endpoint.ClientImpl.doInvoke(ClientImpl.java:541)
    at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:474)
    at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:377)
    at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:330)
    at org.apache.cxf.frontend.ClientProxy.invokeSync(ClientProxy.java:96)
    at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:134)
    ... 2 more
vbopmzt1

vbopmzt11#

找到了它,我希望它能帮助某人,只是用ip地址替换localhost,evreything会很好,看看类似的帖子http://cxf.547215.n5.nabble.com/404-from-web-service-client-td5710925.html

kjthegm6

kjthegm62#

解决方案如下:使用以下内容更新cxf-beans.xml:

<cxf:bus>
        <cxf:inInterceptors>
            <ref bean="inIntercTest"/>
        </cxf:inInterceptors>
        <cxf:outInterceptors>            
            <ref bean="outIntercTest"/>        
        </cxf:outInterceptors>
    </cxf:bus>

而不是:

<cxf:bus>
        <cxf:features>
            <cxf:logging />
            <wsa:addressing />
        </cxf:features>
    </cxf:bus>

相关问题