问题描述
我正在尝试构建具有以下一般要求的客户机/服务器servlet应用程序:
- 客户端和服务器都是码头嵌入式的;
- 服务器公开一个servlet,以便通过
POST
接收json数据; - 连接必须通过SSL保护(即连接将通过互联网通过https完成);
- 我希望仅我的Jetty客户端能够将数据发送到我的服务器,服务器必须拒绝所有其他尝试;
- 服务器和客户端是无人值守的机器(即人工无法插入通过命令行输入的密码);
- 没有明文密码必须存储在客户端设备上。通常,我不希望有人可以打开远程客户端设备并窃取密码并构建能够将数据发送到我的服务器的假远程设备。
我已经通过HTTP
构建了一个运行良好的客户端/服务器应用程序,但是我对安全性感到困惑。
我已经读过,有可能使用客户端/服务器相互身份验证,并且似乎是我在寻找什么,但我没有完整的图片。
在本文档client-certificate-authentication中,关于如何构建共享的受信任CA 或多或少有清晰的解释,但是访问TrustStore
和KeyStore
的密码是在代码中明确。
我想我在拼图中缺少一块瓷砖。
有人可以指出我正确的方向吗?
谢谢
S。
解决方法
我现在有一个简单的答案。
如果只希望您的客户端与服务器通信,那么可以,使用客户端SSL / TLS证书是可以的。
您需要将服务器的SslContextFactory.Server.setNeedClientAuth(true)
设置为true。反过来,这将导致在传入连接建立时设置Java的javax.net.ssl.SSLParameters.setNeedClientAuth(true)
。如果客户端无法提供客户端证书,则连接将关闭,并且不会发送或处理任何HTTP请求。
对于保护客户端证书,这取决于您,您可以做任何您想做的事情,只要它可以产生一个有效的客户端SslContextFactory.Client
,Jetty客户端可以访问该客户端。这包括...
- 使用纯文本密码
- 使用obfuscated passwords(省力,安全性最低)
- 客户端中其他位置的加密密钥库/信任库密码,在最后一分钟提供给SslContextFactory.Client。 (适度的安全性,不难理解)
- 在启动Jetty客户端之前,自己创建
java.security.KeyStore
对象,并将其交给SslContextFactory.Client.setKeyStore(KeyStore)
和SslContextFactory.Client.setTrustStore(KeyStore)
方法。 (更好的安全性,代表您进行更多工作)
您可能要考虑从服务器动态刷新客户端证书的寿命(24小时?),如果遇到滥用情况,可以取消客户端证书(在服务器/ CA端)。 (例如来自多个不同客户端IP的同一客户端证书)