假设我想发布一个商业产品,它有两个组件,用 Java 编写,使用 RESTful API 在本地网络上相互通信。它可以是一个音乐管理器、一个联系人数据库、一本食谱——重要的是这是一个合理且极有可能的场景。
请注意,我说的是两个组件通过本地网络相互通信 --- 而不是与我的服务器通信。
那么如何确保通信安全?
我知道如果我为世界设置一个 HTTP 服务器,我就可以(甚至便宜地)购买 SSL 证书。我已经做到了。但我不能告诉用户去购买证书 --- 他们不知道我在说什么,也永远不知道如何安装它。
那我该怎么办?向每个人发送我自己的自签名证书并做一件非常糟糕的事情,比如 disable certificate validation in Java ?太可怕了,我知道。但至少信息不会以纯文本形式出现。
谁有更好的解决方案?
最佳答案
更新于 2015 年 9 月 20 日以澄清评论中提出的观点
要了解如何做到这一点,让我们检查一下此类应用程序的可能部署方案。假设所讨论的应用程序包含两个组件 - 客户端部分和服务器部分,旨在安装到本地网络上的不同计算机上。我们希望我们的服务器部分只接受安全连接,因此本地网络被认为是敌对的。
安装服务器部分。安装时,使用目标计算机的主机名以编程方式创建自签名证书。如果计算机没有 DNS 记录(如 myserver.mycorp.com),请使用其 IP 地址 - 它必须是静态的,因为我们需要将客户端部分指向它。您可以使用 Bouncy Castle API在代码中创建证书。
将客户端部分安装到另一台计算机上,并将生成的证书复制到安装文件夹中。手动执行此操作可有效地在服务器和客户端之间建立信任。尝试通过恶意网络上的未加密连接自动执行此操作将达不到目的。
由于您在自己的应用程序部分之间严格保护通信,因此您可以完全控制相关应用程序信任的证书。在客户端,创建一个 keystore ,并将生成的证书添加到其中:
FileInputStream fis = new FileInputStream(yourCertificateFile); CertificateFactory cf = CertificateFactory.getInstance("X.509"); X509Certificate c = (X509Certificate)cf.generateCertificate(fis); KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); ks.load(null, aRandomKeystorePasswordCharArray); ks.setCertificateEntry(aUniqueNameForYourCertificate, c); FileOutputStream fos = new FileOutputStream(aRandomKeystoreFileName); ks.store(fos, aRandomKeystorePasswordCharArray); fos.close();
告诉 JVM 您的应用程序只会信任来自其自己的 keystore 的证书。
// replace backslashes '\' with slashes '/' in aRandomKeystoreFileName on Windows System.setProperty("javax.net.ssl.trustStore", aRandomKeystoreFileName); System.setProperty("javax.net.ssl.trustStorePassword", aRandomKeystorePassword);
关于java - 商业产品组件的安全 HTTP 通信,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32505035/