【问题标题】:Understanding SSL in Apache HttpClient (Java)了解 Apache HttpClient (Java) 中的 SSL
【发布时间】:2018-07-05 00:33:47
【问题描述】:

这里有一个自定义 SSL 的示例:
https://hc.apache.org/httpcomponents-client-ga/httpclient/examples/org/apache/http/examples/client/ClientCustomSSL.java

/**
 * This example demonstrates how to create secure connections with a custom SSL
 * context.
 */
public class ClientCustomSSL {

public final static void main(String[] args) throws Exception {
    // Trust own CA and all self-signed certs
    SSLContext sslcontext = SSLContexts.custom()
            .loadTrustMaterial(new File("my.keystore"), "nopassword".toCharArray(),
                    new TrustSelfSignedStrategy())
            .build();
    // Allow TLSv1 protocol only
    SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
            sslcontext,
            new String[] { "TLSv1" },
            null,
            SSLConnectionSocketFactory.getDefaultHostnameVerifier());
    CloseableHttpClient httpclient = HttpClients.custom()
            .setSSLSocketFactory(sslsf)
            .build();
    try {

        HttpGet httpget = new HttpGet("https://httpbin.org/");

        System.out.println("Executing request " + httpget.getRequestLine());

        CloseableHttpResponse response = httpclient.execute(httpget);
        try {
            HttpEntity entity = response.getEntity();

            System.out.println("----------------------------------------");
            System.out.println(response.getStatusLine());
            EntityUtils.consume(entity);
        } finally {
            response.close();
        }
    } finally {
        httpclient.close();
    }
}
}

为什么我们需要它?我已经测试了一个没有任何 SSL 内容的 HttpClient 请求,并且我从 HTTPS url 获得了正确的响应而没有错误。
如果我不添加任何 SSLContext 会有什么问题?
如果让它更安全很重要,这条线是什么?:

.loadTrustMaterial(new File("my.keystore"), "nopassword".toCharArray(),

看来我们需要一些文件和一些密码?

【问题讨论】:

  • 该示例使用密钥库,这意味着它正在执行客户端身份验证。显然,要么您的服务器没有请求客户端证书,要么不介意您没有发送证书,因为您没有配置密钥库。
  • @EJP:代码使用了一个 named 密钥库,并且显然是密钥库格式(因为它是这样读取的,不会引发异常),但它使用内容作为信任材料,即作为信任库,以验证服务器。对于 Apache httpclient 进行客户端身份验证,您调用(其中一个重载)SSLContextBuilder.loadKeyMaterial

标签: java apache-httpclient-4.x


【解决方案1】:

如果您不指定(使用工厂)上下文,Java (JSSE) 会使用包含默认信任库的默认上下文,除非被系统覆盖,否则默认为文件 JRE/lib/security/cacerts(或 jssecacerts,如果存在)特性;见https://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html#CustomizingStores。根据您使用的是 Oracle-was-Sun Java 包、IBM 或 Apple 包或 Android 系统还是 OpenJDK,此默认信任库通常包含与大多数操作系统和浏览器大致相同的一组公共 CA,例如 Verisign Symantec Digicert 和 GoDaddy 以及 LetsEncrypt/Identrust。您是否认为默认的 cacerts 是“安全的”是您的选择;如果不是,您可以更改默认文件的内容,或者让您的代码使用不同的文件,并且要执行后者,是的,您必须指定密钥库文件的文件名及其密码。

该示例使用自定义存储,因为它是自定义 SSL 的示例。如果它使用默认值,它将是默认 SSL 的示例,而不是自定义 SSL 的示例。对于许多实际应用程序,使用默认值就可以了。

除此之外:为协议指定 only TLSv1(意思是 1.0)已经过时了, 很可能被认为是不安全的或至少处于临界状态。它实际上并没有像 SSLv3(以及很久以前的 SSLv2)那样被彻底打破,因为 BEAST 被证明比人们担心的要温和,但是 TLSv1.1 和 1.2 现在已经被广泛实施和使用,而且 1.3 希望不会太远,所以使用 1.0 被广泛使用被认为是不合标准的,例如适用于许多人的 TLSv1.0 支付卡交易自上周末起被彻底禁止。

【讨论】:

  • 在接受答案之前,让我看看我是否理解它:因此,只有当我们需要从 Java 识别一些未包含在默认信任库文件中的 CA 时,我们才需要 SSLContext 对吗?
  • 在这种情况下,为什么要添加密钥库文件而不是信任文件?那个密码是什么?
  • 是的。该文件一个信任库,但是是密钥库格式; Java 使用相同的格式(和相同的KeyStore 类)来包含称为 PrivateKeyEntry 的“key+cert-for-me”或称为 TrustedCertEntry 的“anchor-cert-for-others”(其中大多数锚是 CA)或任何组合;使用keytool -list 列出文件以查看您拥有的文件。密码是文件的密码(如果有);常用的密钥库格式(JKS、JCEKS、BKS、PKCS12)都需要密码,尽管 Java允许密钥库没有密码(例如 Windows-MY、一些 PKCS11 设备)。
  • PS:默认cacerts 的(初始)密码是changeit,它(仅AFAICT)记录在keytool 页面底部附近。但由于这是默认设置,您通常不需要指定它。
猜你喜欢
  • 2014-10-25
  • 2013-10-31
  • 2011-09-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多