HTTPS协议下两种接受自定义Server Certificates的方式

本文介绍了在使用HTTPS协议时,如何处理自定义Server Certificates的问题。针对Java的HttpURLConnection和使用Apache HttpClient(如Rest-Assured)的情况,提供了两种不同的解决方案。对于HttpURLConnection,直接配置信任所有证书;而对于Apache HttpClient,通过自定义SSLSocketFactory并配置Rest-Assured使用该实例来接受自定义证书。

今天在使用Rest-Assured测试登录相关的功能,中间涉及到了HTTPS协议,当然,测试环境中的Certificate是自己定义的,还有一个是已经过期的!使用Rest-Assured访问的时候提示证书过期等各种问题。

花了点时间研究了一下,当然没有研究透彻,只是让它可以工作,留待后面专门研究HTTPS的整个连接创建流程后再补充完整吧。

这里说的两种方式,主要看客户端,如果只是用Java自带的HttpURLConnection等与HTTPS协议的server交互,则可以采用下面第一种方式来接受server的Certificates;如果采用的是Apache Http Client或者各种使用Apache Http Client作为底层交互的工具(如Rest-Assured),需要接受Server Certificates时,可以采用第二种方式:

  • 1,客户端采用HttpURLConnection方式:
TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {
    public X509Certificate[] getAcceptedIssuers() {
        return new java.security.cert.X509Certificate[0];
    }

    public void checkClientTrusted(X509Certificate[] certs, String authType) {
        // do nothing
    }

    public void checkServerTrusted(X509Certificate[] certs, String authType) {
        // do nothing
    }
}};

try {
    SSLContext sc = SSLContext.getInstance("TLS");
    sc.init(null, trustAllCerts, new SecureRandom());
    HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
} catch (Exception e) {
    e.printStackTrace();
}
  • 2,客户端采用HttpClient方式:

    • 2.1 自定义的SSLSocketFactory

      import org.apache.http.conn.ssl.SSLSocketFactory;
      import javax.net.ssl.SSLContext;
      import javax.net.ssl.TrustManager;
      import javax.net.ssl.X509TrustManager;
      import java.io.IOException;
      import java.net.Socket;
      import java.security.*;
      import java.security.cert.CertificateException;
      import java.security.cert.X509Certificate;
      
      public class AcceptAllCertsProtocolSocketFactory extends SSLSocketFactory {
          SSLContext sslContext = SSLContext.getInstance("TLS");
      
          public AcceptAllCertsProtocolSocketFactory(KeyStore truststore) throws NoSuchAlgorithmException,
                  KeyManagementException, KeyStoreException, UnrecoverableKeyException {
              super(truststore);
              TrustManager tm = new X509TrustManager() {
                  @Override
                  public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
                      // do nothing
                  }
      
                  @Override
                  public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
                      // do nothing
                  }
      
      
                  public X509Certificate[] getAcceptedIssuers() {
                      return null;
                  }
              };
      
              sslContext.init(null, new TrustManager[]{tm}, null);
          }
      
      
          @Override
          public Socket createSocket(Socket socket, String host, int port, boolean autoClose)
                  throws IOException {
              return sslContext.getSocketFactory().createSocket(socket, host, port, autoClose);
          }
      
          @Override
          public Socket createSocket() throws IOException {
              return sslContext.getSocketFactory().createSocket();
          }
      }
    • 2.2 这里以使用Rest-Assured为例,在创建HttpClient实例的时候,使用上述SSLSocketFactory:

    import com.jayway.restassured.config.HttpClientConfig;
    import org.apache.http.HttpVersion;
    import org.apache.http.client.HttpClient;
    import org.apache.http.conn.ClientConnectionManager;
    import org.apache.http.conn.scheme.PlainSocketFactory;
    import org.apache.http.conn.scheme.Scheme;
    import org.apache.http.conn.scheme.SchemeRegistry;
    import org.apache.http.conn.ssl.SSLSocketFactory;
    import org.apache.http.impl.client.DefaultHttpClient;
    import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
    import org.apache.http.params.BasicHttpParams;
    import org.apache.http.params.HttpParams;
    import org.apache.http.params.HttpProtocolParams;
    import org.apache.http.protocol.HTTP;
    
    import java.security.KeyStore;
    
    public class AcceptAllCertsHttpClientFactory implements HttpClientConfig.HttpClientFactory {
    
        @Override
        public HttpClient createHttpClient() {
            try {
                KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
                trustStore.load(null, null);
    
                AcceptAllCertsProtocolSocketFactory sf = new AcceptAllCertsProtocolSocketFactory(trustStore);
                sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
    
                HttpParams params = new BasicHttpParams();
                HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
                HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);
    
                SchemeRegistry registry = new SchemeRegistry();
                registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
                registry.register(new Scheme("https", sf, 443));
    
                ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry);
    
                return new DefaultHttpClient(ccm, params);
            } catch (Exception e) {
                return new DefaultHttpClient();
            }
        }
    }
    • 2.3,确保Rest-Assured底层使用了上述HttpClient实例,而非默认的DefaultHttpClient:
    RestAssured.config = RestAssured.config().httpClient(HttpClientConfig.httpClientConfig().httpClientFactory(new AcceptAllCertsHttpClientFactory()));

引用
- 1, Trusting all certificates using HttpClient over HTTPS
- 2, Java SSL/TLS ignore expired cert? (java.security.cert.CertPathValidatorException: timestamp check failed)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值