- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我一直在玩 Netty(版本 4.0.24)的 SecureChatServer 示例,并且插入了我自己的 keystore (基于在以下两篇文章 post 1 和 post2 中找到的答案。请参阅下面的代码片段.
我看到的问题是,当我运行一个客户端实例时,一切都按预期工作,但是当我尝试启动更多客户端实例时,我在服务器和客户端上都遇到了异常(异常文本见下文)和那时服务器停止响应。
我希望这里有人可以阐明我做错了什么。
这是处理加载我的 keyStore 和创建客户端/服务器使用的 SSLContext 实例的类(出于明显的原因,我省略了我的 keystore 值):
package com.test.securechat;
import java.io.ByteArrayInputStream;
import java.security.KeyStore;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;
import com.test.util.Key;
import com.pragmafs.util.encryption.Base64Coder;
/**
* Creates SSLContext instances from a static (String representation) keystore
* See http://maxrohde.com/2013/09/07/setting-up-ssl-with-netty/
*/
public class SslContextFactory {
private static final String PROTOCOL = "TLS";
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("JKS");
ks.load(new ByteArrayInputStream(Base64Coder.decode(Key.SSL.getKey())), Base64Coder.decodeString(Key.SSL.getPwd()).toCharArray());
// Set up key manager factory to use our key store
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(ks, Base64Coder.decodeString(Key.SSL.getPwd()).toCharArray());
// truststore
KeyStore ts = KeyStore.getInstance("JKS");
ts.load(new ByteArrayInputStream(Base64Coder.decode(Key.SSL.getKey())), Base64Coder.decodeString(Key.SSL.getPwd()).toCharArray());
// set up trust manager factory to use our trust store
trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(ts);
// Initialize the SSLContext to work with our key managers.
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 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() {
// Unused
}
}
这是服务器代码:
package com.test.securechat;
import java.net.InetAddress;
import javax.net.ssl.SSLEngine;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import io.netty.handler.codec.Delimiters;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.ssl.SslHandler;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.GenericFutureListener;
import io.netty.util.concurrent.GlobalEventExecutor;
/**
* Simple SSL chat server
*/
public final class SecureChatServer {
static final int PORT = Integer.parseInt(System.getProperty("port", "8992"));
public static void main(String[] args) throws Exception {
SSLEngine sslEngine = SslContextFactory.getServerContext().createSSLEngine();
sslEngine.setUseClientMode(false);
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.handler(new LoggingHandler(LogLevel.INFO))
.childHandler(new SecureChatServerInitializer(sslEngine));
b.bind(PORT).sync().channel().closeFuture().sync();
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
private static class SecureChatServerInitializer extends ChannelInitializer<SocketChannel> {
private final SSLEngine sslCtx;
public SecureChatServerInitializer(SSLEngine sslCtx) {
this.sslCtx = sslCtx;
}
@Override
public void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(new SslHandler(sslCtx));
pipeline.addLast(new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter()));
pipeline.addLast(new StringDecoder());
pipeline.addLast(new StringEncoder());
// and then business logic.
pipeline.addLast(new SecureChatServerHandler());
}
}
private static class SecureChatServerHandler extends SimpleChannelInboundHandler<String> {
static final ChannelGroup channels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
@Override
public void channelActive(final ChannelHandlerContext ctx) {
// Once session is secured, send a greeting and register the channel to the global channel
// list so the channel received the messages from others.
ctx.pipeline().get(SslHandler.class).handshakeFuture().addListener(
new GenericFutureListener<Future<Channel>>() {
@Override
public void operationComplete(Future<Channel> future) throws Exception {
ctx.writeAndFlush(
"Welcome to " + InetAddress.getLocalHost().getHostName() + " secure chat service!\n");
ctx.writeAndFlush(
"Your session is protected by " +
ctx.pipeline().get(SslHandler.class).engine().getSession().getCipherSuite() +
" cipher suite.\n");
channels.add(ctx.channel());
}
});
}
@Override
public void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
// Send the received message to all channels but the current one.
for (Channel c : channels) {
if (c != ctx.channel()) {
c.writeAndFlush("[" + ctx.channel().remoteAddress() + "] " + msg + '\n');
} else {
c.writeAndFlush("[you] " + msg + '\n');
}
}
// Close the connection if the client has sent 'bye'.
if ("bye".equals(msg.toLowerCase())) {
ctx.close();
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
cause.printStackTrace();
ctx.close();
}
}
}
客户端代码:
package com.test.securechat;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import javax.net.ssl.SSLEngine;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import io.netty.handler.codec.Delimiters;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.handler.ssl.SslHandler;
/**
* Simple SSL chat client
*/
public final class SecureChatClient {
static final String HOST = System.getProperty("host", "127.0.0.1");
static final int PORT = Integer.parseInt(System.getProperty("port", "8992"));
public static void main(String[] args) throws Exception {
SSLEngine engine = SslContextFactory.getClientContext().createSSLEngine();
engine.setUseClientMode(true);
EventLoopGroup group = new NioEventLoopGroup();
try {
Bootstrap b = new Bootstrap();
b.group(group)
.channel(NioSocketChannel.class)
.handler(new SecureChatClientInitializer(engine));
// Start the connection attempt.
Channel ch = b.connect(HOST, PORT).sync().channel();
// Read commands from the stdin.
ChannelFuture lastWriteFuture = null;
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
for (; ; ) {
String line = in.readLine();
if (line == null) {
break;
}
// Sends the received line to the server.
lastWriteFuture = ch.writeAndFlush(line + "\r\n");
// If user typed the 'bye' command, wait until the server closes
// the connection.
if ("bye".equals(line.toLowerCase())) {
ch.closeFuture().sync();
break;
}
}
// Wait until all messages are flushed before closing the channel.
if (lastWriteFuture != null) {
lastWriteFuture.sync();
}
} finally {
// The connection is closed automatically on shutdown.
group.shutdownGracefully();
}
}
private static class SecureChatClientInitializer extends ChannelInitializer<SocketChannel> {
private final SSLEngine sslCtx;
public SecureChatClientInitializer(SSLEngine sslCtx) {
this.sslCtx = sslCtx;
}
@Override
public void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
// Add SSL handler first to encrypt and decrypt everything.
// In this example, we use a bogus certificate in the server side
// and accept any invalid certificates in the client side.
// You will need something more complicated to identify both
// and server in the real world.
//pipeline.addLast(sslCtx.newHandler(ch.alloc(), SecureChatClient.HOST, SecureChatClient.PORT));
pipeline.addLast(new SslHandler(sslCtx));
// On top of the SSL handler, add the text line codec.
pipeline.addLast(new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter()));
pipeline.addLast(new StringDecoder());
pipeline.addLast(new StringEncoder());
//pipeline.addLast(new LoggingHandler(LogLevel.INFO));
// and then business logic.
pipeline.addLast(new SecureChatClientHandler());
}
}
private static class SecureChatClientHandler extends SimpleChannelInboundHandler<String> {
@Override
public void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
System.err.println(msg);
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
cause.printStackTrace();
ctx.close();
}
}
}
服务器异常:
INFO: [id: 0x5eb2ac7a, /0:0:0:0:0:0:0:0:8992] RECEIVED: [id: 0x7d7a7dca, /127.0.0.1:55932 => /127.0.0.1:8992]
io.netty.handler.codec.DecoderException: javax.net.ssl.SSLHandshakeException: ciphertext sanity check failed
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:278)
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:147)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:333)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:319)
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:787)
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:130)
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:116)
at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:137)
at java.lang.Thread.run(Thread.java:744)
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:995)
at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:921)
at io.netty.handler.ssl.SslHandler.decode(SslHandler.java:867)
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:247)
... 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
客户端异常:
io.netty.handler.codec.DecoderException: javax.net.ssl.SSLException: Received fatal alert: <UNKNOWN ALERT: 170>
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:278)
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:147)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:333)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:319)
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:787)
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:130)
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:116)
at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:137)
at java.lang.Thread.run(Thread.java:744)
Caused by: javax.net.ssl.SSLException: Received fatal alert: <UNKNOWN ALERT: 170>
at sun.security.ssl.Alerts.getSSLException(Alerts.java:208)
at sun.security.ssl.SSLEngineImpl.fatal(SSLEngineImpl.java:1619)
at sun.security.ssl.SSLEngineImpl.fatal(SSLEngineImpl.java:1587)
at sun.security.ssl.SSLEngineImpl.recvAlert(SSLEngineImpl.java:1756)
at sun.security.ssl.SSLEngineImpl.readRecord(SSLEngineImpl.java:1060)
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:995)
at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:921)
at io.netty.handler.ssl.SslHandler.decode(SslHandler.java:867)
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:247)
... 12 more
最佳答案
你能解释一下为什么你用信任工厂初始化你的服务器 SSLContext
但不向客户端 SSLContext
初始化方法提供任何 key 工厂吗?
您是否正在尝试进行相互身份验证?如果是这样,您还需要调用 SSLEngine.setNeedClientAuth(true)
。
你见过SslContext.java吗? ?这可能能够简化您的初始化过程并减少您构建自己的 SSLContext
对象的需要。如果您的证书是 X509 并且您的 key 是 PKCS#8 格式,那么您不必担心信任管理器或 key 管理器,因为 SslContext可以读取这些并为您初始化所有内容(通过 newClientContext
和 newServerContext
)。如果需要,这些接口(interface)还支持相互身份验证。
关于java - 网络 SSL : Chat Client example with custom keystore is unable to accept multiple connections,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26746332/
我正在使用 Mechanize 配置 ssl , 根据 document我需要设置 agent.cert = 'example.cer' agent.key='example.cer' 但是我怎样才能
我有一个表格,允许人们将士兵添加到列表中,该列表可以很好地传输到 mysql。如果我在没有变量的情况下这样做甚至很好,但是一旦我尝试添加一个如下所示。 // Get Variable from Loc
使用 .htaccess 重写,我想要: http://example.com 重定向到:http://www.example.comhttps://www.example.com 重定向到:http
我想将所有流量重定向到 https://www.sitename.com 例子 http://sitename.com --> https://www.sitename.com http://www.
我只有 example.com 的 SSL 证书,并且想同时重定向 http://example.com和 http://*.example.com 到 https://example.com使用 n
我有服务器 A,它托管我们在 www.example.com 上的主要站点;我们有一个涵盖 *.example.com 的 SSL 证书。 在我们网站的安全部分,我们希望向我们编写并托管在单独机器/I
我正在努力平衡多行上的一些文本,并且我正在添加手动换行符以将文本均匀地分割在各行上。为了弄清楚这一点,我需要查看在哪里添加“\n”来测试我的代码,但我发现的唯一方法是将其全部打印为字符: ["T",
我在我们的域中安装了 Apache 和 Tomcat 服务器,因为我有超过 25 个服务,一些服务由 Apache 处理,一些服务由 Tomcat 处理。 tomcat 服务显示 http://exa
编辑:问题终于解决了。详细信息可以在此消息末尾的疑难解答部分中找到。 我在这里保留了详细的步骤,以防可能对某人有所帮助。 设置OpenLDAP I-创建服务器 该文档通常已经过时,并且您会找到多种实现
这个问题在这里已经有了答案: offsetting an html anchor to adjust for fixed header [duplicate] (28 个答案) 关闭 8 年前。
目前谷歌将我的网站链接显示为... example.com/ ...但是,我希望它显示为... example.com 我确实有以下元数据 ...下面是我的 htaccess 文件... Index
我使用 Microsoft Visual Studio 2012。当我将代码示例放入 C# 类/方法的 XML 注释中时,我想知道:引用我的程序集的用户将如何看到该代码示例? 我试图引用我自己的程序集
我对正则表达式还很陌生,无法真正弄清楚它是如何工作的。我试过这个: function change_email($email){ return preg_match('/^[\w]$/', $e
我正在使用 Hibernate 版本 4.3.5.Final。这里的问题是 Hibernate 找到 Foo 类型的实体,其中属性 address 的大小写不同(例如“BLAFOO”)。但是,在我的示
我为环境特定变量(如用户名和密码)设置了一个环境 YAML 文件。要在我的应用程序中使用这些变量,我需要使用 APP_CONFIG['username']而不是 APP_CONFIG[:usernam
已关闭。这个问题是 off-topic 。目前不接受答案。 想要改进这个问题吗? Update the question所以它是on-topic用于堆栈溢出。 已关闭10 年前。 Improve th
这个问题在这里已经有了答案: Does Python have a string 'contains' substring method? (10 个答案) 关闭 8 年前。 我想检查发件人 hea
我已经在 https://arieldemian.it 上配置了 SSL/TLS但似乎https://www.arieldemian.it不安全。这是为什么?我需要注册他们两个吗?我正在使用 http
当我使用 ProGuard 时,com.example.** 和 com.example.**{*;} 之间的区别是什么?例如,每种情况会发生什么情况? -keep class com.examp
我的主页的内容是根据使用 slug“home”对数据库的查询提取的。例如,如果我在地址栏中输入 example.com/home,它会根据看到的“/home”查询数据库并提取正确的内容(使用变量“$p
我是一名优秀的程序员,十分优秀!