How to set up Apache CXF client to use WebSphere truststore? (Receiving “No trusted certificate found” exception.)

后端 未结 4 740
情深已故
情深已故 2020-12-31 14:19

First, I\'ll start with a summary. I\'m using an Apache CXF client to communicate over SSL with an Apache CXF service provider that is using a self-signed certificate. I i

相关标签:
4条回答
  • 2020-12-31 14:44

    I don't think you can use the WAS keystores just like that with external component (Apache CXF). You must probably build and use your own TrustManager. There seem to be several working examples around for that.

    0 讨论(0)
  • 2020-12-31 14:45

    CXF is probably using the wrong SSL socket factory.

    Try adding this to your Spring config:

    <http-conf:conduit name="*.http-conduit">
        <http-conf:tlsClientParameters useHttpsURLConnectionDefaultSslSocketFactory="true"/>
    </http-conf:conduit>
    
    0 讨论(0)
  • 2020-12-31 14:47

    Looking at how CXF and WAS work, it is fairly straightforward to access the Websphere's SSLSocketFactory and pass it to CXF using an outbound interceptor.

    If you use the following class:

    public class WebsphereSslOutInterceptor extends AbstractPhaseInterceptor<Message> {
    
      private String sslAlias = null;
    
      public WebsphereSslOutInterceptor() {
        super(Phase.SETUP);
      }
    
      public void handleMessage(Message message) throws Fault {
        Conduit conduit = message.getExchange().getConduit(message);
        if (conduit instanceof HTTPConduit) {
          HTTPConduit httpConduit = (HTTPConduit)conduit;
          String endpoint = (String) message.get(Message.ENDPOINT_ADDRESS);
          if (endpoint != null) {
            try {
              URL endpointUrl = new URL(endpoint);
              Map<String, String> connectionInfo = new HashMap<String, String>();
    
              connectionInfo.put(
                JSSEHelper.CONNECTION_INFO_REMOTE_HOST, 
                endpointUrl.getHost());
              connectionInfo.put(
                JSSEHelper.CONNECTION_INFO_REMOTE_PORT, 
                Integer.toString(endpointUrl.getPort()));
              connectionInfo.put(
                JSSEHelper.CONNECTION_INFO_DIRECTION, 
                JSSEHelper.DIRECTION_OUTBOUND);
              SSLSocketFactory factory = 
                JSSEHelper.getInstance().getSSLSocketFactory(
                  sslAlias, 
                  connectionInfo, 
                  null);
    
              TLSClientParameters tlsClientParameters = httpConduit.getTlsClientParameters();
              if (tlsClientParameters != null) {
                tlsClientParameters.setSSLSocketFactory(factory);
              }
            } catch (MalformedURLException e) {
              throw new Fault(e);
            } catch (SSLException e) {
              throw new Fault(e);
            }
          }
        }
      }
    
      public void setSslAlias(String sslAlias) {
        this.sslAlias = sslAlias;
      }
    }
    

    Then you'll be able to hook up to Websphere's SSLSocketFactory and can optionally use the "Dynamic Outbound Endpoint SSL Configuration" settings to specify any client certs, by specifying the interceptor in the jaxws:client tag:

      <jaxws:client id="proxyName"
            serviceClass="proxyClass"
            address="${web.service.endpointaddress}">
    
        <jaxws:outInterceptors>
            <bean class="my.pkg.WebsphereSslOutInterceptor" />
        </jaxws:outInterceptors>
    </jaxws:client>
    

    As an aside, if the sslAlias property is declared in the WebsphereSslOutInterceptor, a client certificate can be chosen based on its alias.

    Because this is using the SSLSocketFactory from Websphere, the trust stores will also be used from Websphere.

    EDIT:

    I used CXF 2.3.6 and Websphere 6.1

    0 讨论(0)
  • 2020-12-31 14:49

    beny23's solution works great for me on WAS7, with the following modifications (reason: httpConduit.getTlsClientParameters() might be null):

    Replace this part:

        TLSClientParameters tlsClientParameters = httpConduit.getTlsClientParameters();
        if (tlsClientParameters != null) {
          tlsClientParameters.setSSLSocketFactory(factory);
        }
    

    With this:

        TLSClientParameters tlsClientParameters = httpConduit.getTlsClientParameters();
        if (tlsClientParameters == null) {
          tlsClientParameters = new TLSClientParameters();
          httpConduit.setTlsClientParameters(tlsClientParameters);
        }
        tlsClientParameters.setSSLSocketFactory(factory);
    
    0 讨论(0)
提交回复
热议问题