HTTPS(三)之JAVA 不校验HTTPS服务器证书

本篇主要描述JAVA经常遇到的场景:不校验服务器CA证书。主要包含以下内容:

  • HttpsURLConnection不校验服务器CA证书
  • Spring RestTemplate不校验服务器CA证书

HttpsURLConnection不校验服务器CA证书

有些情况下,虽然服务器端使用的是https协议,但是其证书不是由权威机构颁发的,客户端如果使用jdk默认的证书会校验失败。为了在项目初期进行调试,我们可以忽略服务器证书校验。由前一篇文章可知,要达到不校验服务器证书的目的,必须将hostname校验和CA证书校验同时关闭。
要忽略hostname校验,可以通过前一篇文章JAVA中HTTPS那些事儿中的HostnameVerifier小节介绍的case4场景来实现。要忽略证书校验,则需要自定义SSLSocketFactory。整体代码如下:

public void ignore() throws NoSuchAlgorithmException, KeyManagementException {
        // 自定义证书校验器
        TrustManager[] trustAllCerts = new TrustManager[] {
          new X509TrustManager() {
            @Override
            public void checkClientTrusted(X509Certificate[] x509Certificates, 
                                           String s) throws CertificateException {}
            @Override
            public void checkServerTrusted(X509Certificate[] x509Certificates, 
                                           String s) throws CertificateException {}
            @Override
            public X509Certificate[] getAcceptedIssuers() { 
                   return new X509Certificate[0]; 
            }
          }
        };
        SSLContext sc = SSLContext.getInstance("SSL");
        sc.init(null, trustAllCerts, new java.security.SecureRandom());
        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());

        // 自定义hostname校验器
        HostnameVerifier allHostsValid = new HostnameVerifier() {
            @Override
            public boolean verify(String hostname, SSLSession session) {
                return true;
            }
        };
        HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
    }

从代码中可以看到setDefaultSSLSocketFactory和setDefaultHostnameVerifier都是HttpsURLConnection的静态方法,也就是此处的设置是全局的。所以在进行实际的HTTPS访问前,调用一次ignore方法,即可在后续所有的HTTPS访问中达到不校验服务器CA证书的目的。

Spring RestTemplate不校验服务器CA证书

Spring中的RestTemplate是用于访问Restful服务的便捷工具类,该类依靠更下层的组件来完成网络请求。默认使用JDK中的HttpURLConnection,同时支持配置Apache HttpComponents HttpClient(4.3+)、OkHttp(2.x and 3.x)、Netty4。所以要使RestTemplate在访问HTTPS服务时忽略证书校验,其实需要配置的是底层的实现组件。

  • 如果使用默认实现HttpURLConnection,如果要忽略证书只需要按照前一小节HttpsURLConnection不校验服务器CA证书进行操作即可。
    Apache HttpComponents HttpClient(4.3+)不校验CA证书
  • Apache的HttpClient也是依赖于标准的java加密(Java
    Cryptography-JCE)和安全socket扩展(Secure
    Sockets-JSEE),所以需要忽略证书同样需要创建一个javax.net.ssl.SSLContext。与HttpsURLConnection一样Apache
    HttpClient提供可选的HostnameVerifier功能,并提供两个实现类DefaultHostnameVerifier和NoopHostnameVerifier,第一个采用RFC
    2818规则校验hostname,第二个则不进行校验。如果需要不校验服务器CA证书,Apache
    HttpClient提供了一个帮助了可以直接使用,代码如下:
public static void main(String[] args) throws IOException, KeyStoreException,
            NoSuchAlgorithmException, KeyManagementException {
        // 配置Apache HttpClient
        HttpClient httpClient = HttpClients
                .custom()
                .setSSLContext(
                        new SSLContextBuilder()
                                .loadTrustMaterial(null, TrustAllStrategy.INSTANCE)
                                .build()
                )
                .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
                .build();
        // 让RestTemplate使用Apache HttpClient访问网络
        HttpComponentsClientHttpRequestFactory requestFactory =
                new HttpComponentsClientHttpRequestFactory();
        requestFactory.setHttpClient(httpClient);
        
        RestTemplate restTemplate = new RestTemplate(requestFactory);
        restTemplate.getMessageConverters().add(new FormHttpMessageConverter());
        String resp = restTemplate.getForObject(IgnoreServerCerts.testUrl,
                String.class);
        System.out.println(resp);
    }

其他
RestTemplate同时支持使用OkHttp(2.x and 3.x)和Netty4,但是由于项目中暂未所用,我对这些组件也不熟悉,如果有使用到可以自行研究。

总结

本篇文章主要介绍的是java中怎么实现不校验HTTPS服务器证书,主要介绍JDK中的HttpURLConnection和Apache HttpComponents HttpClient(4.3+)怎么忽略。同时明确Spring的RestTemplate是依赖于底层网络访问组件实现的Http访问,要忽略证书只需要配置底层组件即可。
至此,本系列文章主要部分已技术,还有最后一篇可供选择阅读使用keytool模拟CA证书颁发过程。

本文系转载博文,作者信息如下:
作者:雪落孤村
链接:https://www.jianshu.com/p/ea07a32ec85d

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在使用OkHttp时,如果我们想要忽略HTTPS证书校验,可以通过自定义一个用于信任所有证书的信任管理器来实现。 首先,我们需要创建一个TrustManager的实现类,该类用于信任所有的证书。可以通过重写checkClientTrusted和checkServerTrusted方法来实现,这两个方法在验证客户端和服务器证书时被调用,我们可以在这里不进行任何校验直接返回一个空的链表。 接下来,我们需要创建一个SSLContext对象,并使用我们自定义的TrustManager进行初始化。然后,使用这个SSLContext对象创建一个SSLSocketFactory对象。 最后,我们将这个SSLSocketFactory对象设置到OkHttpClient中的SSL socket factory中,这样OkHttp在发起HTTPS请求时就会忽略证书校验了。 下面是一个示例代码: ```java // 创建信任所有证书的TrustManager X509TrustManager trustManager = new X509TrustManager() { @Override public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { // 可以不进行任何校验直接返回 } @Override public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { // 可以不进行任何校验直接返回 } @Override public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; } }; try { // 创建一个SSLContext并使用我们的TrustManager初始化 SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(null, new TrustManager[]{trustManager}, null); // 创建SSLSocketFactory SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory(); OkHttpClient client = new OkHttpClient.Builder() .sslSocketFactory(sslSocketFactory, trustManager) .build(); // 使用client发起HTTPS请求 // ... } catch (Exception e) { e.printStackTrace(); } ``` 需要注意的是,忽略HTTPS证书校验存在一定的安全风险,因此建议仅在开发环境中使用,并在正式环境中使用正规的证书进行校验

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值