Java SSL套接字客户端认证

3

我有一个简单的服务器程序,收集来自多个硬件设备在开放式无线网络中的数据。我希望确保连接到我的端口的任何人都不能发送命令或监听我的流量,因此我需要服务器验证客户端。我找到了一些示例,但大多数似乎采用从客户端验证服务器的方法。我对SSL和Socket编程不熟悉。

在客户端方面,我有

KeyStore keystore = KeyStore.getInstance("JKS");
keystore.load(new FileInputStream("KeyStore"), "password".toCharArray());
TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
tmf.init(keystore);

SSLContext context = SSLContext.getInstance("TLS");
TrustManager[] trustManagers = tmf.getTrustManagers();

context.init(null, trustManagers, null);

SSLSocketFactory sf = context.getSocketFactory();
return (SSLSocket) sf.createSocket(host, port);

在服务器上,我有以下内容

KeyStore ks = KeyStore.getInstance("JKS");
ks.load(newFileInputStream("server"),"password".toCharArray());
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(ks, "password".toCharArray());
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(kmf.getKeyManagers(), null, null);
SSLServerSocketFactory ssf = sc.getServerSocketFactory();
server = (SSLServerSocket) ssf.createServerSocket(this.port);

我不确定所有代码的作用,但是从我找到的示例来看,它是双向身份验证,可能过于复杂了。我认为我只需要其中一段代码,但不理解SSL足够深入,无法确定哪个。是哪一方需要密钥库?谁需要密钥和证书?谢谢。


1
双向认证并不是“过度保护”,它包括服务器认证和客户端认证,如果您不希望其他人监听您的流量,这正是您所需要的。如果服务器需要信任设备,那么设备也需要信任服务器,这是理所当然的。 - user207421
感谢您的回复。我最担心的是有人连接到我的端口并尝试向服务器发送命令。我对服务器身份验证并不那么担心,因为这些设备将长时间保持与服务器的连接。我想通过保持单向连接来减少维护和复杂性。 - jamesSampica
1个回答

3

如果您只想在现有的服务器身份验证基础上添加客户端身份验证,只需在服务器代码末尾添加以下行:

server.setNeedClientAuth(true);

如果你只想让服务器授权客户端而不是反过来,那么在服务器上调用server.setUseClientMode(true),并在客户端创建SSLSocket时调用setUseClientMode(false)。请注意,此选项意味着客户端设备可能会连接到其他人的服务器,并且无法知道这一点。
无论哪种情况,服务器都需要一个信任存储库——它可以与其密钥库相同——其中包含客户端提供的证书的副本。客户端将需要具有呈现此证书的密钥对。

不确定您是否需要提到 server.setUseClientMode(true),这只会使答案变得比必要的复杂。这也使TCP服务器成为SSL/TLS客户端,反之亦然,因此它不再是真正的客户端证书验证。 - Bruno
2
那部分被包含是因为提问者似乎只想要客户端认证 - 其中“客户端”指的是“TCP客户端”,而不是“SSL / TLS客户端”。我同意这不是正常的用例,但我想完全回答问题。 - Warren Dew

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接