Java Netty 4.0.27 HTTP over SSL(如安全聊天示例中所示)在多个客户端上失败
我按照安全聊天示例实现了一个HTTPS服务器。对于单个客户机,这很好。对于多个客户端,我会遇到服务器端异常[1]。我使用soapui和Jmeter作为我的两个客户机。这对于SOAPUI或JMeter都很好 我的服务器代码如下Java Netty 4.0.27 HTTP over SSL(如安全聊天示例中所示)在多个客户端上失败,java,ssl,https,netty,Java,Ssl,Https,Netty,我按照安全聊天示例实现了一个HTTPS服务器。对于单个客户机,这很好。对于多个客户端,我会遇到服务器端异常[1]。我使用soapui和Jmeter作为我的两个客户机。这对于SOAPUI或JMeter都很好 我的服务器代码如下 SSLEngine engine = SSLContextFactory.getServerContext().createSSLEngine(); engine.setUseClientMode(false); EventLoopGroup bos
SSLEngine engine = SSLContextFactory.getServerContext().createSSLEngine();
engine.setUseClientMode(false);
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.option(ChannelOption.SO_BACKLOG, 200)
.childOption(ChannelOption.ALLOCATOR,
PooledByteBufAllocator.DEFAULT)
.childHandler(new ServerInitializer(engine));
ChannelFuture future = bootstrap.bind(8002).sync();
future.addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) {
System.out.println("#### Bootstrap Bind Future #####");
}
});
ChannelFuture closef = future.channel().closeFuture();
closef.addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) {
System.out.println("#### Channel Close Future #####");
}
});
closef.sync();
} catch (Exception e) {
e.printStackTrace();
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
try {
bossGroup.terminationFuture().sync();
workerGroup.terminationFuture().sync();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
服务器初始值设定项类
public class ServerInitializer extends ChannelInitializer<SocketChannel> {
private SSLEngine sslEngine;
public ServerInitializer(SSLEngine sslEngine) {
this.sslEngine = sslEngine;
}
@Override
public void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(new SslHandler(sslEngine));
pipeline.addLast("decoder", new HttpRequestDecoder());
pipeline.addLast("aggregator", new HttpObjectAggregator(Integer.MAX_VALUE));
pipeline.addLast("encoder", new HttpResponseEncoder());
pipeline.addLast(new StreamHttpServerHandler());
}
}
[1]
您必须为每个
SslHandler
创建一个新的SSLEngine
。不要将SSLEngine
传递给ServerInitializer
,而是传递SslContext
并通过ServerInitializer.initChannel()中的SslContext.newHandler()
创建一个新的SslHandler
。有关更多信息,请查看SecureChat示例:
您必须为每个SslHandler
创建一个新的SSLEngine
。不要将SSLEngine
传递给ServerInitializer
,而是传递SslContext
并通过ServerInitializer.initChannel()中的SslContext.newHandler()
创建一个新的SslHandler
。有关更多信息,请查看SecureChat示例:
您必须为每个SslHandler
创建一个新的SSLEngine
。不要将SSLEngine
传递给ServerInitializer
,而是传递SslContext
并通过ServerInitializer.initChannel()中的SslContext.newHandler()
创建一个新的SslHandler
。有关更多信息,请查看SecureChat示例:
您必须为每个SslHandler
创建一个新的SSLEngine
。不要将SSLEngine
传递给ServerInitializer
,而是传递SslContext
并通过ServerInitializer.initChannel()中的SslContext.newHandler()
创建一个新的SslHandler
。有关更多信息,请查看SecureChat示例:
谢谢。这正是问题所在!谢谢这正是问题所在!谢谢这正是问题所在!谢谢这正是问题所在!
public class SSLContextFactory {
private static final String PROTOCOL = "TLS";
private static final String KEY_TYPE = "JKS";
private static final SSLContext SERVER_CONTEXT;
private static final SSLContext CLIENT_CONTEXT;
private static final TrustManagerFactory trustManagerFactory;
static {
SSLContext serverContext = null;
SSLContext clientContext = null;
try {
KeyStore ks = KeyStore.getInstance(KEY_TYPE);
ks.load(new ByteArrayInputStream(Base64.decodeBase64(SSLKey.getKey())), new String(Base64.decodeBase64(SSLKey.getKeyPass())).toCharArray());
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(ks, new String(Base64.decodeBase64(SSLKey.getKeyPass())).toCharArray());
KeyStore ts = KeyStore.getInstance(KEY_TYPE);
ts.load(new ByteArrayInputStream(Base64.decodeBase64(SSLKey.getKey())), new String(Base64.decodeBase64(SSLKey.getKeyPass())).toCharArray());
trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(ts);
serverContext = SSLContext.getInstance(PROTOCOL); serverContext.init(kmf.getKeyManagers(),trustManagerFactory.getTrustManagers(), null);
clientContext = SSLContext.getInstance(PROTOCOL);
clientContext.init(null, trustManagerFactory.getTrustManagers(), null);
} catch (Exception e) {
throw new Error("Failed to initialize the Netty SSLContext", e);
}
SERVER_CONTEXT = serverContext;
CLIENT_CONTEXT = clientContext;
}
public static SSLContext getServerContext() {
return SERVER_CONTEXT;
}
public static SSLContext getClientContext() {
return CLIENT_CONTEXT;
}
public static TrustManagerFactory getTrustManagerFactory() {
return trustManagerFactory;
}
private SSLContextFactory() {
}
io.netty.handler.codec.DecoderException: javax.net.ssl.SSLHandshakeException: ciphertext sanity check failed
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:346)
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:229)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:339)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:324)
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:847)
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:131)
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:511)
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:468)
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:382)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:354)
at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:111)
at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:137)
at java.lang.Thread.run(Thread.java:745)
Caused by: javax.net.ssl.SSLHandshakeException: ciphertext sanity check failed
at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
at sun.security.ssl.SSLEngineImpl.fatal(SSLEngineImpl.java:1683)
at sun.security.ssl.SSLEngineImpl.readRecord(SSLEngineImpl.java:959)
at sun.security.ssl.SSLEngineImpl.readNetRecord(SSLEngineImpl.java:884)
at sun.security.ssl.SSLEngineImpl.unwrap(SSLEngineImpl.java:758)
at javax.net.ssl.SSLEngine.unwrap(SSLEngine.java:624)
at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1114)
at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:981)
at io.netty.handler.ssl.SslHandler.decode(SslHandler.java:934)
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:315)
... 12 more
Caused by: javax.crypto.BadPaddingException: ciphertext sanity check failed
at sun.security.ssl.InputRecord.decrypt(InputRecord.java:147)
at sun.security.ssl.EngineInputRecord.decrypt(EngineInputRecord.java:192)
at sun.security.ssl.SSLEngineImpl.readRecord(SSLEngineImpl.java:953)
... 19 more