我是靠谱客的博主 完美可乐,最近开发中收集的这篇文章主要介绍java jdk 加密,与jdk8加密以为http2启用ALPN,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

I have been searching how to implement Conscrypt SSL provider using conscrypt-openjdk-uber-1.4.1.jar for jdk8 to support ALPN for making a http2(using apache httpclient 5) connection to a server as jdk8 does not support ALPN by default or the other solution is to migrate to jdk9(or higher) which is not feasible for now as our product is heavily dependent on jdk8

I have been searching extensively for some docs or examples to implement but I could not find one.

I have tried to insert conscrypt provider as default and my program takes it as default provider but still it fails to connect with http2 server, my example is as follows,

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

Security.insertProviderAt(new OpenSSLProvider(), 1);

final SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(new TrustAllStrategy()).build();

final PoolingAsyncClientConnectionManager connectionManager = PoolingAsyncClientConnectionManagerBuilder.create().setTlsStrategy(new H2TlsStrategy(sslContext, NoopHostnameVerifier.INSTANCE)).build();

final IOReactorConfig ioReactorConfig = IOReactorConfig.custom().setSoTimeout(Timeout.ofSeconds(5)).build();

final MinimalHttpAsyncClient client = HttpAsyncClients.createMinimal(HttpVersionPolicy.FORCE_HTTP_2, H2Config.DEFAULT, null, ioReactorConfig, connectionManager);

client.start();

final HttpHost target = new HttpHost("localhost", 8082, "https");

final Future leaseFuture = client.lease(target, null);

final AsyncClientEndpoint endpoint = leaseFuture.get(10, TimeUnit.SECONDS);

try {

String[] requestUris = new String[] {"/"};

CountDownLatch latch = new CountDownLatch(requestUris.length);

for (final String requestUri: requestUris) {

SimpleHttpRequest request = SimpleHttpRequest.get(target, requestUri);

endpoint.execute(SimpleRequestProducer.create(request), SimpleResponseConsumer.create(), new FutureCallback() {

@Override

public void completed(final SimpleHttpResponse response) {

latch.countDown();

System.out.println(requestUri + "->" + response.getCode());

System.out.println(response.getBody());

}

@Override

public void failed(final Exception ex) {

latch.countDown();

System.out.println(requestUri + "->" + ex);

ex.printStackTrace();

}

@Override

public void cancelled() {

latch.countDown();

System.out.println(requestUri + " cancelled");

}

});

}

latch.await();

} catch (Exception e) {

e.printStackTrace();

}finally {

endpoint.releaseAndReuse();

}

client.shutdown(ShutdownType.GRACEFUL);

}

this programs gives the output as

org.apache.hc.core5.http.ConnectionClosedException: Connection closed

org.apache.hc.core5.http.ConnectionClosedException: Connection closed

at org.apache.hc.core5.http2.impl.nio.FrameInputBuffer.read(FrameInputBuffer.java:146)

at org.apache.hc.core5.http2.impl.nio.AbstractHttp2StreamMultiplexer.onInput(AbstractHttp2StreamMultiplexer.java:415)

at org.apache.hc.core5.http2.impl.nio.AbstractHttp2IOEventHandler.inputReady(AbstractHttp2IOEventHandler.java:63)

at org.apache.hc.core5.http2.impl.nio.ClientHttp2IOEventHandler.inputReady(ClientHttp2IOEventHandler.java:38)

at org.apache.hc.core5.reactor.InternalDataChannel.onIOEvent(InternalDataChannel.java:117)

at org.apache.hc.core5.reactor.InternalChannel.handleIOEvent(InternalChannel.java:50)

at org.apache.hc.core5.reactor.SingleCoreIOReactor.processEvents(SingleCoreIOReactor.java:173)

at org.apache.hc.core5.reactor.SingleCoreIOReactor.doExecute(SingleCoreIOReactor.java:123)

at org.apache.hc.core5.reactor.AbstractSingleCoreIOReactor.execute(AbstractSingleCoreIOReactor.java:80)

at org.apache.hc.core5.reactor.IOReactorWorker.run(IOReactorWorker.java:44)

at java.lang.Thread.run(Thread.java:748)

If I print the provider and version it prints as Conscrypt version 1.0 and JDK 1.8.0_162, but still it fails to connect with a http2 endpoint

same chunk of code works perfectly if I connect using jdk9 with default provider, what I m missing here in conscrypt configuration?

Any help is appreciated

Thanks in advance

解决方案

Just replacing the default JSSE provider with Conscrypt is not enough. One also needs a custom TlsStrategy that can take advantage of Conscrypt APIs.

This what works for me with Java 1.8 and Conscrypt 1.4.1

static class ConscriptClientTlsStrategy implements TlsStrategy {

private final SSLContext sslContext;

public ConscriptClientTlsStrategy(final SSLContext sslContext) {

this.sslContext = Args.notNull(sslContext, "SSL context");

}

@Override

public boolean upgrade(

final TransportSecurityLayer tlsSession,

final HttpHost host,

final SocketAddress localAddress,

final SocketAddress remoteAddress,

final Object attachment) {

final String scheme = host != null ? host.getSchemeName() : null;

if (URIScheme.HTTPS.same(scheme)) {

tlsSession.startTls(

sslContext,

host,

SSLBufferMode.STATIC,

(endpoint, sslEngine) -> {

final SSLParameters sslParameters = sslEngine.getSSLParameters();

sslParameters.setProtocols(H2TlsSupport.excludeBlacklistedProtocols(sslParameters.getProtocols()));

sslParameters.setCipherSuites(H2TlsSupport.excludeBlacklistedCiphers(sslParameters.getCipherSuites()));

H2TlsSupport.setEnableRetransmissions(sslParameters, false);

final HttpVersionPolicy versionPolicy = attachment instanceof HttpVersionPolicy ?

(HttpVersionPolicy) attachment : HttpVersionPolicy.NEGOTIATE;

final String[] appProtocols;

switch (versionPolicy) {

case FORCE_HTTP_1:

appProtocols = new String[] { ApplicationProtocols.HTTP_1_1.id };

break;

case FORCE_HTTP_2:

appProtocols = new String[] { ApplicationProtocols.HTTP_2.id };

break;

default:

appProtocols = new String[] { ApplicationProtocols.HTTP_2.id, ApplicationProtocols.HTTP_1_1.id };

}

if (Conscrypt.isConscrypt(sslEngine)) {

sslEngine.setSSLParameters(sslParameters);

Conscrypt.setApplicationProtocols(sslEngine, appProtocols);

} else {

H2TlsSupport.setApplicationProtocols(sslParameters, appProtocols);

sslEngine.setSSLParameters(sslParameters);

}

},

(endpoint, sslEngine) -> {

if (Conscrypt.isConscrypt(sslEngine)) {

return new TlsDetails(sslEngine.getSession(), Conscrypt.getApplicationProtocol(sslEngine));

}

return null;

});

return true;

}

return false;

}

}

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

final SSLContext sslContext = SSLContexts.custom()

.setProvider(Conscrypt.newProvider())

.build();

final PoolingAsyncClientConnectionManager cm = PoolingAsyncClientConnectionManagerBuilder.create()

.setTlsStrategy(new ConscriptClientTlsStrategy(sslContext))

.build();

try (CloseableHttpAsyncClient client = HttpAsyncClients.custom()

.setVersionPolicy(HttpVersionPolicy.NEGOTIATE)

.setConnectionManager(cm)

.build()) {

client.start();

final HttpHost target = new HttpHost("nghttp2.org", 443, "https");

final String requestUri = "/httpbin";

final HttpClientContext clientContext = HttpClientContext.create();

final SimpleHttpRequest request = SimpleHttpRequests.GET.create(target, requestUri);

final Future future = client.execute(

SimpleRequestProducer.create(request),

SimpleResponseConsumer.create(),

clientContext,

new FutureCallback() {

@Override

public void completed(final SimpleHttpResponse response) {

System.out.println(requestUri + "->" + response.getCode() + " " +

clientContext.getProtocolVersion());

System.out.println(response.getBody());

final SSLSession sslSession = clientContext.getSSLSession();

if (sslSession != null) {

System.out.println("SSL protocol " + sslSession.getProtocol());

System.out.println("SSL cipher suite " + sslSession.getCipherSuite());

}

}

@Override

public void failed(final Exception ex) {

System.out.println(requestUri + "->" + ex);

}

@Override

public void cancelled() {

System.out.println(requestUri + " cancelled");

}

});

future.get();

System.out.println("Shutting down");

client.shutdown(CloseMode.GRACEFUL);

}

}

最后

以上就是完美可乐为你收集整理的java jdk 加密,与jdk8加密以为http2启用ALPN的全部内容,希望文章能够帮你解决java jdk 加密,与jdk8加密以为http2启用ALPN所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(48)

评论列表共有 0 条评论

立即
投稿
返回
顶部