gpt4 book ai didi

ssl - Netty 客户端在需要相互认证的 SSL 握手过程中不发送客户端证书

转载 作者:太空宇宙 更新时间:2023-11-03 13:37:29 26 4
gpt4 key购买 nike

我是 Netty 的新手,我尝试编写一个使用相互身份验证的回显服务器和客户端。不幸的是,它不工作,客户端不发送其客户端证书并且服务器按预期断开连接。下面概述了我到目前为止所做的事情和客户端代码 - 可能包含一些错误或者我错过了一些重要的事情。感谢您经历这一切!

这就是我所拥有的:

  • Netty 版本 4.1.0.CR1
  • 可在服务器上下载的有效 keystore 、信任库和 CRL
  • 直接使用 JSSE 的回显服务器和客户端的完整实现(按预期工作)
  • 使用 Netty 的回显服务器的工作实现(与基于 JSSE 的客户端一起使用时工作正常)
  • 基于Netty的不发送客户端证书的客户端

客户端代码:

channel 处理程序:

package info.junius.tutorial.echo.netty.tls;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.util.CharsetUtil;

public class EchoClientHandler extends SimpleChannelInboundHandler<ByteBuf>
{
@Override
public void channelRead0(ChannelHandlerContext ctx, ByteBuf in)
{
System.out.println("CLIENT: Received echo from server:\n" + in.toString(CharsetUtil.UTF_8));
}

@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
{
cause.printStackTrace();
ctx.close();
}
}

channel 初始化器:

package info.junius.tutorial.echo.netty.tls;

import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.handler.ssl.SslContext;

public class ClientChannelInitializer extends ChannelInitializer<Channel>
{
private final SslContext context;
private final String peerHost;
private final int peerPort;

public ClientChannelInitializer(SslContext context, String peerHost, int peerPort)
{
this.context = context;
this.peerHost = peerHost;
this.peerPort = peerPort;
}

@Override
protected void initChannel(Channel channel) throws Exception
{
// Add SSL handler first to encrypt and decrypt everything.
channel.pipeline().addLast(this.context.newHandler(channel.alloc(), this.peerHost, this.peerPort));
// and then business logic.
channel.pipeline().addLast(new EchoClientHandler());
}
}

回显客户端:

package info.junius.tutorial.echo.netty.tls;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;

public class EchoClient
{
private final String host;
private final int port;

public EchoClient(String host, int port)
{
super();
this.host = host;
this.port = port;
}

public static void main(String[] args) throws Exception
{
if (args.length != 2)
{
System.err.println("Usage: " + EchoClient.class.getSimpleName() + " <host> <port>");
}
else
{
// Security.addProvider(new BouncyCastleProvider());
String host = args[0];
int port = Integer.parseInt(args[1]);
new EchoClient(host, port).start();
}
}

public void start() throws Exception
{
TlsContextUtil tlsContextUtil = new TlsContextUtil();
ChannelInitializer<Channel> channelInitializer = new ClientChannelInitializer(tlsContextUtil.getClientContext(), this.host, this.port);
EventLoopGroup group = new NioEventLoopGroup();
try
{
Bootstrap b = new Bootstrap();
b.group(group).channel(NioSocketChannel.class).handler(channelInitializer);
Channel channel = b.connect(this.host, this.port).sync().channel();
ChannelFuture writeFuture = channel.writeAndFlush("Hello from netty client!\n");
// channel.closeFuture().sync();
writeFuture.sync();
}
finally
{
group.shutdownGracefully().sync();
}
}
}

以及返回 SslContext 的实用程序类:

...
public SslContext getClientContext() throws IOException
{
SslContext sslContext = null;
try
{
// truststore
TrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX", "SunJSSE");
tmf.init(this.getKeystore(TRUSTSTORE));

// keystore holding client certificate
KeyManagerFactory kmf = KeyManagerFactory.getInstance("PKIX", "SunJSSE");
kmf.init(this.getKeystore(CLIENT_KEYSTORE), KEYSTORE_PW);

SslContextBuilder builder = SslContextBuilder.forClient().keyManager(kmf).trustManager(tmf).ciphers(PFS_CIPHERS);

// build context
sslContext = builder.build();
}
catch (NoSuchAlgorithmException
| NoSuchProviderException
| KeyStoreException
| IllegalStateException
| UnrecoverableKeyException e)
{
throw new IOException("Unable to create client TLS context", e);
}
return sslContext;
}
...

虚拟机参数:

-Djavax.net.debug=all -Djava.security.debug="certpath crl" -Dcom.sun.net.ssl.checkRevocation=true -Dcom.sun.security.enableCRLDP=true

我确信我的错误一定出在 Netty 客户端代码中,因为系统仅在使用 JSSE 时工作正常。非常感谢任何帮助!

干杯,安迪

最佳答案

好的,我已经开始工作了。实际上是我的客户端代码出错了(该代码是基于 Netty 自带的安全聊天示例)。所以我将其更改为回显示例中使用的版本:

回声客户端处理程序:

@Override
public void channelActive(ChannelHandlerContext ctx)
{
// When notified that the channel is active send a message.
System.out.println("CLIENT: Sending request to server...");
ctx.writeAndFlush(Unpooled.copiedBuffer("Mein Schnitzel ist kaputt!\n", CharsetUtil.UTF_8));
}

和 EchoClient:

try
{
Bootstrap b = new Bootstrap();
b.group(group).channel(NioSocketChannel.class).handler(channelInitializer);
ChannelFuture f = b.connect(this.host, this.port).sync();
f.channel().closeFuture().sync();
}
finally
{
group.shutdownGracefully().sync();
}

之前的代码太早断开连接,以至于握手从未完成。

关于ssl - Netty 客户端在需要相互认证的 SSL 握手过程中不发送客户端证书,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35167546/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com