Websphere - Spring 集成 SSL 问题

Websphere - Spring Integration SSL issue

我们的 Spring 集成应用程序在 Websphere 上运行。它是 SSL 外部服务的客户端。

我已经使用 Retrive 从端口 [进入默认信任库] 导入证书,提供主机和 443 端口。在 WebSphere 上启用了跟踪,它似乎正在查看 cacert 文件而不是 trust.p12。

[18-2-19 13:44:59:154 CET] 00000063 SystemOut     O 2019-02-18 13:44:59.153  INFO 30426 --- [ver.startup : 0] pertySourcedRequestMappingHandlerMapping : Mapped URL path [/v2/api-docs] onto method [public org.springframework.http.ResponseEntity<springfox.documentation.spring.web.json.Json> springfox.documentation.swagger2.web.Swagger2Controller.getDocumentation(java.lang.String,javax.servlet.http.HttpServletRequest)]
[18-2-19 13:44:59:826 CET] 00000063 SystemOut     O keyStore is: /srv/opt/IBM/WebSphere/AppServer/java/8.0/jre/lib/security/cacerts

代码:

public class PreemptiveMessageSender extends HttpComponentsMessageSender {

    @Autowired
    private Environment env; 

    private String host;
    private String userId;
    private String password;

    public PreemptiveMessageSender() {
        super();
    }

    public PreemptiveMessageSender(HttpClient httpClient) {
        super(httpClient);
    }

    @Override
    protected HttpContext createContext(URI uri) {

        HttpHost targetHost = new HttpHost(host, 443, "https");

        String decryptedPassword = getDecryptedPassword();

         CredentialsProvider credsProvider = new BasicCredentialsProvider();
         credsProvider.setCredentials(AuthScope.ANY, 
                    new UsernamePasswordCredentials(userId, decryptedPassword));

         AuthCache authCache = new BasicAuthCache();
         authCache.put(targetHost, new BasicScheme());

         // Add AuthCache to the execution context
         final HttpClientContext context = HttpClientContext.create();
         context.setCredentialsProvider(credsProvider);
         context.setAuthCache(authCache);

         return context;        
    }

    private String getDecryptedPassword() {
        BasicTextEncryptor textEncrypt = new BasicTextEncryptor();

        textEncrypt.setPassword(env.getProperty("KEY_PASSWORD"));
        return textEncrypt.decrypt(password);       
    }

    @Override
    public WebServiceConnection createConnection(URI uri) throws IOException {

        HttpPost httpPost = new HttpPost(uri);
        if (isAcceptGzipEncoding()) {
            httpPost.addHeader(HttpTransportConstants.HEADER_ACCEPT_ENCODING,
                    HttpTransportConstants.CONTENT_ENCODING_GZIP);
        }
        HttpContext httpContext = createContext(uri);
        return new CustomHttpComponentsConnection(getHttpClient(), httpPost, httpContext);
    }

    ... 
}

错误:

"exception": "org.springframework.ws.client.WebServiceIOException", "message": "I/O error: com.ibm.jsse2.util.h: PKIX path building failed: java.security.cert.CertPathBuilderException: PKIXCertPathBuilderImpl could not build a valid CertPath.; internal cause is: \n\tjava.security.cert.CertPathValidatorException: The certificate issued by CN=ODC Test Root CA - G1, O=ODC Test, C=TU is not trusted; internal cause is: \n\tjava.security.cert.CertPathValidatorException: Certificate chaining error; nested exception is javax.net.ssl.SSLHandshakeException: com.ibm.jsse2.util.h: PKIX path building failed: java.security.cert.CertPathBuilderException: PKIXCertPathBuilderImpl could not build a valid CertPath.; internal cause is: \n\tjava.security.cert.CertPathValidatorException: The certificate issued by CN=ODC Test Root CA - G1, O=ODC Test, C=TU is not trusted; internal cause is: \n\tjava.security.cert.CertPathValidatorException: Certificate chaining error",

问题: 使用 java cacert 的 Spring 集成是否存在此问题?如何让它使用WebSphere的trust store?

我先说我对Spring一无所知。但是鉴于您谈论的行为,它必须创建自己的 SSLContext 实例。这将导致它绕过 WebSphere SSL 设置。它必须做类似 SSLContext.getInstance() 的事情来创建自己的实例,或者它可能做类似 SSLContext.getDefault() 的事情,其中​​ returns 你是 JDK 的默认 SSLContext。两者都不会为您提供 WebSphere SSLContext。

https://developer.ibm.com/answers/questions/394270/im-using-an-apache-httpclient-to-make-an-outbound/

HttpClient theClient = HttpClientBuilder.create().useSystemProperties().addInterceptorFirst(new RemoveSoapHeadersInterceptor()).build();

private static class RemoveSoapHeadersInterceptor implements HttpRequestInterceptor {
        @Override
        public void process(HttpRequest request, HttpContext context) throws HttpException, IOException {
            if (request instanceof HttpEntityEnclosingRequest) {
                if (request.containsHeader(HTTP.TRANSFER_ENCODING)) {
                    request.removeHeaders(HTTP.TRANSFER_ENCODING);
                }
                if (request.containsHeader(HTTP.CONTENT_LEN)) {
                    request.removeHeaders(HTTP.CONTENT_LEN);
                }
            }
        }   
    }