2016-05-07 172 views
1

自签名证书是未由证书颁发机构(CA)签名的证书。 JAVA存储大多数CA的证书(这里是jre/lib/security/cacerts),所以如果你想连接到一个有CA签名的证书的https站点,没有特殊的代码。 (用于HTTP调用相同的代码将工作)Apache HttpClient自签名证书

所以基本上

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客户端?

回答

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中,那么我们需要创建一个文件以将它传递给文件对象(它不适用于jar文件)

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