【问题标题】:Apache HttpClient SelfSigned certificatesApache HttpClient 自签名证书
【发布时间】:2016-05-08 02:59:22
【问题描述】:

自签名证书是未经证书颁发机构 (CA) 签名的证书。 JAVA 存储大多数 CA 的证书(此处为 jre/lib/security/cacerts),因此如果您想使用 CA 签名的证书连接到 https 站点,则没有特殊代码。 (同样的 http 调用代码也可以)

基本上

CloseableHttpClient httpclient = HttpClients.createDefault();
HttpGet httpGet = new HttpGet(https_url);
httpclient.execute(httpGet)

但如果我们有自签名证书,那么我们需要配置客户端并使其工作。否则我们会看到

sun.security.validator.ValidatorException:PKIX 路径构建失败:sun.security.provider.certpath.SunCertPathBuilderException:无法找到到请求目标的有效证书路径

javax.net.ssl.SSLPeerUnverifiedException: 主机名 'localhost' 与对等方提供的证书主题不匹配 ...

这种情况下如何配置http客户端?

【问题讨论】:

    标签: ssl apache-httpclient-4.x self-signed


    【解决方案1】:

    httpclient 4.x

    方法 1

    通过调试选项配置 TrustStrore

    -Djavax.net.ssl.trustStore=/Users/amodpandey/.keystore
    

    即使不传递密码(信任库的密码),Java 也能够读取信任库

    但即使在这之后你也可能面临

    javax.net.ssl.SSLPeerUnverifiedException: 主机名 'localhost' 与对等方提供的证书主题不匹配 ...

    CloseableHttpClient httpClient =
      HttpClientBuilder.create()
            .setSSLHostnameVerifier(new HostnameVerifier() {              
              @Override
              public boolean verify(String arg0, SSLSession arg1) {
                return true;
              }
            })
            .build();
    

    它有效..

    方法2

    全部放在代码中

    CloseableHttpClient httpClient =
      HttpClientBuilder.create()
            .setSslcontext(SSLContexts.custom().loadTrustMaterial(new File(Thread.currentThread().getContextClassLoader().getResource("keystore").getFile())).build())
            .setSSLHostnameVerifier(new HostnameVerifier() {              
              @Override
              public boolean verify(String arg0, SSLSession arg1) {
                return true;
              }
            })
            .build();
    

    方法 3

    使用连接管理器时

    使用时忽略setSslcontext和setSSLHostnameVerifier

    .setConnectionManager(connectionManager)
    

    所以应该配置连接管理器

    Files.copy(ClassLoader.getSystemResourceAsStream("keystore"), Paths.get(URI.create("file:/tmp/keystore")),
        StandardCopyOption.REPLACE_EXISTING);
    Registry<ConnectionSocketFactory> socketFactoryRegistry =
        RegistryBuilder
            .<ConnectionSocketFactory>create()
            .register(
                "https",
                new SSLConnectionSocketFactory(SSLContextBuilder.create()
                    .loadTrustMaterial(new File("/tmp/keystore")).build(),
                    new HostnameVerifier() {
                      @Override
                      public boolean verify(String hostname, SSLSession session) {
                        return true;
                      }
                    })).register("http", PlainConnectionSocketFactory.INSTANCE).build();
    
    PoolingHttpClientConnectionManager connectionManager =
        new PoolingHttpClientConnectionManager(socketFactoryRegistry);
    
    CloseableHttpClient httpClient =
        HttpClientBuilder.create()
            .setConnectionManager(connectionManager)
            .build();
    

    注意

    • -Djavax.net.debug=all 调试选项非常有助于查看正在使用的证书
    • SSLContext 使用 File,如果我们计划将证书与代码一起打包到 Jar 中,那么我们需要创建一个文件以将其传递给 File 对象(它不适用于 jar 中的文件)

      Files.copy(ClassLoader.getSystemResourceAsStream("keystore"),Paths.get(URI.create("file:/tmp/utskeystore")),StandardCopyOption.REPLACE_EXISTING)

    【讨论】:

      猜你喜欢
      • 2017-02-16
      • 2021-05-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多