簡體   English   中英

帶有Jersey for SSL的ApacheConnectorProvider引發錯誤

[英]ApacheConnectorProvider with Jersey for SSL throws Error

我正在嘗試使用SSL URL發布服務呼叫。 我有一個例外。

javax.ws.rs.ProcessingException: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at org.glassfish.jersey.apache.connector.ApacheConnector.apply(ApacheConnector.java:517)
    at org.glassfish.jersey.client.ClientRuntime.invoke(ClientRuntime.java:246)
    at org.glassfish.jersey.client.JerseyInvocation$1.call(JerseyInvocation.java:667)
    at org.glassfish.jersey.client.JerseyInvocation$1.call(JerseyInvocation.java:664)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:315).

我正在使用Jersey的Spring,並嘗試使用ApacheClient(要使用原因,在Weblogic上,它使用Weblogic特定的HTTP處理程序,我知道我們可以使用“ DUseSunHttpHandler = true”,但我不想在生產中使用該功能)。

請注意,僅使用Jersey實施,它就可以在Tomcat和Weblogic上與http一起使用。 但是,使用HTTPS可以在Tomcat中工作,而不能在Weblogic中工作。 因此,選擇ApacheConnectionProvider,從那里開始在Tomcat中也不起作用。

POM條目

<dependency>
        <groupId>org.glassfish.jersey.core</groupId>
        <artifactId>jersey-client</artifactId>
        <version>2.15</version>
        <scope>compile</scope>
    </dependency>
    <dependency>
        <groupId>org.glassfish.jersey.core</groupId>
        <artifactId>jersey-common</artifactId>
        <version>2.15</version>
        <scope>compile</scope>
    </dependency>
    <dependency>
        <groupId>javax.ws.rs</groupId>
        <artifactId>javax.ws.rs-api</artifactId>
        <version>2.0.1</version>
        <scope>compile</scope>
    </dependency>
    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpclient</artifactId>
        <version>4.4</version>
    </dependency>
    <dependency>
        <groupId>org.glassfish.jersey.connectors</groupId>
        <artifactId>jersey-apache-connector</artifactId>
        <version>2.15</version>
    </dependency>

public Client getClient() {
        ClientConfig clientConfig = new ClientConfig();
        clientConfig.property(ApacheClientProperties.CONNECTION_MANAGER, new PoolingHttpClientConnectionManager());
        //config your ssl for apache connector
        SslConfigurator sslConfig = SslConfigurator.newInstance();

        String trustStoreFile = "C:\\Development\\svn\\ecomm-webapp\\profiles\\uat\\workflowtrust.jks";
        String trustStorePassword ="ABC12";
        String keyStoreFile = "C:\\Development\\svn\\ecomm-webapp\\profiles\\uat\\workflow.jks";
        String keyPassword ="abc12";
        sslConfig.trustStoreFile(trustStoreFile).keyStoreFile(keyStoreFile).keyStorePassword(trustStorePassword).trustStorePassword(trustStorePassword).securityProtocol("SSL");
        clientConfig.property(ApacheClientProperties.SSL_CONFIG, sslConfig);
        ApacheConnectorProvider connector = new ApacheConnectorProvider();
        clientConfig.connectorProvider(connector);

        return  ClientBuilder.newClient(clientConfig);
    }

呼叫碼

public <T> T postXmlFile(final File inputXml, final String targetUrl, Class<T> resultResponse, final RestfulServiceVerifier<T> restfulServiceVerifier) throws FunctionalException {
        return post(MediaType.APPLICATION_XML_TYPE, MediaType.TEXT_XML_TYPE, inputXml, targetUrl, resultResponse, restfulServiceVerifier);
    }

    private <T> T post(final MediaType type, final MediaType accept, final Object entity, final String targetUrl, Class<T> resultResponse, final RestfulServiceVerifier<T> restfulServiceVerifier) throws FunctionalException {
        Response response = null;
        int responseStatus = -1;
        T result = null;
        while (restfulServiceVerifier.hasNextWorkFlowHit()) {
            try {
                response = restFulWebTargetFactory.getClient().target(targetUrl)
                        .request(type)
                        .post(Entity.entity(entity, accept));

                responseStatus = response.getStatus();
                if(EcommConstants.WORKFLOW_ORDER_PROPOSAL_SUCCESS_CODE == responseStatus) {
                    final String resultInString =  response.readEntity(String.class);
                    //for audit purpose
                    if (LOG_XML_MESSAGE) {
                        log.info("XML Response "+ resultInString);
                    }
                    result = unMarshalXML(resultInString, resultResponse);
                    restfulServiceVerifier.checkResponse(result, responseStatus);
                }

            } catch (WorkFlowRetryException workFlowException) {
                throw new FunctionalException("WebService post failed. ", workFlowException);
            }catch (WorkFlowValidationException workFlowValidationException) {
                log.error("Service Response Validation Exception " + workFlowValidationException.getErrorCode() + " Error Description " + workFlowValidationException.getDescription(), workFlowValidationException);
            }catch (final Exception e) {
                log.error("Exception occurred" , e);
            } finally {
                if(null != response) {
                    response.close();
                }
            }
        }
        if(-1 == responseStatus) {
            throw new FunctionalException("WebService post failed. ", new Exception());
        }
        return result;
    }

我已修復,請找到解決方案。 我更改了getClient()方法。

  1. 我創建了org.apache.http.conn.ssl.DefaultHostnameVerifier。 這是我更改的代碼片段DefaultHostnameVerifier(我只需要默認一個)
  2. 使用信任庫和密鑰配置文件配置的SslConfigurator
  3. 創建了LayeredConnectionSocketFactory並從SslConfigurator和defaultHostnameVerifier注入SSLContext
  4. 為http和https創建一個注冊表
  5. 創建ClientConfig以使用帶有注入注冊表的PoolingHttpClientConnectionManager設置連接管理器
  6. 並將SSL Config設置為Client Config
  7. 創建了ApacheConnectorProvider並將其設置為clientConfig

代碼樣例

private SslConfigurator createSSLContext() {
        return SslConfigurator.newInstance()
                .trustStoreFile(trustStoreFile)
                .trustStorePassword(trustStorePassword)
                .keyStoreFile(keyStoreFile)
                .keyPassword(keyPassword).securityProtocol("SSL");
    }


    @Override
    public Client getClient() {

        HostnameVerifier defaultHostnameVerifier=new DefaultHostnameVerifier();
        SslConfigurator sslConfig = createSSLContext();
        LayeredConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(
                sslConfig.createSSLContext(),
                defaultHostnameVerifier);

        final Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
                .register("http", PlainConnectionSocketFactory.getSocketFactory())
                .register("https", sslSocketFactory)
                .build();

        ClientConfig clientConfig = new ClientConfig();
        clientConfig.property(ApacheClientProperties.CONNECTION_MANAGER, new PoolingHttpClientConnectionManager(registry));

        clientConfig.property(ApacheClientProperties.SSL_CONFIG, sslConfig);

        ApacheConnectorProvider connector = new ApacheConnectorProvider();
        clientConfig.connectorProvider(connector);
        return ClientBuilder.newBuilder().withConfig(clientConfig).build();
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM