1. 程式人生 > >記錄一下訪問https報doesn‘t contain CN or DNS sub錯誤

記錄一下訪問https報doesn‘t contain CN or DNS sub錯誤

lse mail main follow rust log 版本說明 def end

版本說明

httpclinet:4.3.1
jdk:1.6
tomcat:6

異常信息

Caused by: javax.net.ssl.SSLException: Certificate for <**> doesn‘t contain CN or DNS subjectAlt
        at org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:178)
        at org.apache.http.conn.ssl.BrowserCompatHostnameVerifier.verify(BrowserCompatHostnameVerifier.java:54)
        at org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:152)
        at org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:133)
        at org.apache.http.conn.ssl.SSLConnectionSocketFactory.verifyHostname(SSLConnectionSocketFactory.java:291)
        at org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:262)
        at org.apache.http.impl.conn.HttpClientConnectionOperator.connect(HttpClientConnectionOperator.java:118)
        at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:314)
        at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:357)
        at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:218)
        at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:194)
        at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:85)
        at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:108)
        at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:186)
        at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)
        at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:106)
        ... 18 more

背景

使用httpclient忽略證書發起https請求,代碼如下

package cn.org.pcac.ries.httpService.util;
import java.io.IOException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.X509HostnameVerifier;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
public class HttpsSend {
    public static void main(String[] args) throws Exception {
        String url = "";
        List<NameValuePair> formparams = new ArrayList<NameValuePair>();
        HttpPost httpPost = new HttpPost(url);
        // 設置客戶超時
        RequestConfig defaultRequestConfig = RequestConfig.custom()
                .setSocketTimeout(9000).setConnectTimeout(9000)
                .setConnectionRequestTimeout(9000)
                .setStaleConnectionCheckEnabled(true).build();
        // 設置服務端
        RequestConfig requestConfig = RequestConfig.copy(defaultRequestConfig)
                .build();
        formparams.add(new BasicNameValuePair("param", ""));
        httpPost.setConfig(requestConfig);
        CloseableHttpClient httpclient = null;
        httpclient = HttpClients.custom()
                .setDefaultRequestConfig(defaultRequestConfig).build();
        SSLContext sslcontext = null;
        if (url.indexOf("https") == 0) {
            sslcontext = createIgnoreVerifySSL();
            httpclient = HttpClients.custom().setDefaultRequestConfig(defaultRequestConfig)
                    .setSslcontext(sslcontext).build();
        }
        UrlEncodedFormEntity uefEntity = new UrlEncodedFormEntity(formparams,
                "UTF-8");
        httpPost.setEntity(uefEntity);
        HttpResponse response = httpclient.execute(httpPost);
        HttpEntity entity = response.getEntity();
        if (entity != null) {
            // 獲得返回報文
            String respons = EntityUtils.toString(entity, "UTF-8");
            EntityUtils.consume(entity);
            System.out.println(respons);
        }
    }
    public static SSLContext createIgnoreVerifySSL() throws NoSuchAlgorithmException, KeyManagementException {  
        SSLContext sc = SSLContext.getInstance("TLS");  
        X509TrustManager trustManager = new X509TrustManager() {  
            @Override  
            public void checkClientTrusted(  
                    java.security.cert.X509Certificate[] paramArrayOfX509Certificate,  
                    String paramString) throws CertificateException {  
            }  

            @Override  
            public void checkServerTrusted(  
                    java.security.cert.X509Certificate[] paramArrayOfX509Certificate,  
                    String paramString) throws CertificateException {  
            }  

            @Override  
            public java.security.cert.X509Certificate[] getAcceptedIssuers() {  
                return null;  
            }  
        };  

        sc.init(null, new TrustManager[] { trustManager }, null);  
        return sc;  
    } 
}

錯誤原因

跟蹤源碼,異常信息如下所示:
技術分享圖片
技術分享圖片
技術分享圖片
訪問網站的證書為自簽證書,缺少CN=等信息,但是我已經忽略證書校驗了為什麽還會出現這個問題呢?
發現初始化CloseableHttpClient時,有如下代碼:
技術分享圖片
因此修改初始化CloseableHttpClient,將
httpclient = HttpClients.custom().setDefaultRequestConfig(defaultRequestConfig)
.setSslcontext(sslcontext).build();
改成
httpclient = HttpClients.custom().setDefaultRequestConfig(defaultRequestConfig)

.setHostnameVerifier(hostnameVerifier)
.setSslcontext(sslcontext).build();
增加變量
public static X509HostnameVerifier hostnameVerifier = new X509HostnameVerifier() {@Override
br/>@Override
return true;
}

    @Override
    public void verify(String host, String[] cns, String[] subjectAlts)
            throws SSLException {

    }

    @Override
    public void verify(String host, X509Certificate cert) throws SSLException {

    }

    @Override
    public void verify(String host, SSLSocket ssl) throws IOException {

    }
};

記錄一下訪問https報doesn‘t contain CN or DNS sub錯誤