1. 程式人生 > >SSLHandshakeException: No subject alternative names matching IP address found

SSLHandshakeException: No subject alternative names matching IP address found

一、異常日誌

javax.net.ssl.SSLHandshakeException:
    Caused by: java.security.cert.CertificateException: No subject alternative names matching IP address 110.75.244.16 found
        at sun.security.util.HostnameChecker.matchIP(Unknown Source)
	at sun.security.util.HostnameChecker.match(Unknown Source)
	at sun.security.ssl.X509TrustManagerImpl.checkIdentity(Unknown Source)
	at sun.security.ssl.X509TrustManagerImpl.checkIdentity(Unknown Source)
	at sun.security.ssl.X509TrustManagerImpl.checkTrusted(Unknown Source)
	at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(Unknown Source)
	... 12 more

二、異常程式碼

public class SslHandshakeExc_NsanMatchingIp{
	
	public static void main(String[] args) throws Exception {

		URL url = new URL("https://110.75.244.16/gateway.do"); // openapi.alipay.com

		HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();

		conn.connect();

		InputStream is = conn.getInputStream();
		BufferedReader br = new BufferedReader(new InputStreamReader(is));

		String line;
		while ((line = br.readLine()) != null) {
			System.out.println(line);
		}

		br.close();
		is.close();

	}
	
}

三、處理方案

public class SslHandshakeExc_NsanMatchingIp{
	
	public static void main(String[] args) throws Exception {

		URL url = new URL("https://110.75.244.16/gateway.do"); // openapi.alipay.com

		HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();

		// 新增部分
		conn.setHostnameVerifier(new SslHandshakeExc_NsanMatchingIp().new TrustAnyHostnameVerifier());

		conn.connect();

		InputStream is = conn.getInputStream();
		BufferedReader br = new BufferedReader(new InputStreamReader(is));

		String line;
		while ((line = br.readLine()) != null) {
			System.out.println(line);
		}

		br.close();
		is.close();

	}

	// 定製Verifier
	public class TrustAnyHostnameVerifier implements HostnameVerifier {
		public boolean verify(String hostname, SSLSession session) {
			return true;
		}
	}
	
}

四、補充說明

    在建立 SSL 連線時,HttpsClient 步驟並進行基本的伺服器身份驗證,以防止 URL 欺騙,其中包括驗證伺服器的名稱是否在證書中
    HttpsClient 主要使用 HostNameChecker 檢查主機名和證書中指定的名稱。如果失敗了,HostNameVerifier 就會出現,它被用來驗證主機名
    在 HostNameVerifier 沒有被重寫時,預設是這個驗證是錯誤的,也就意味著 HostNameChecker 失敗後就會丟擲這個異常
    HostNameChecker 在實現上,如果傳入的主機名是 IP 地址,將由 matchIP 方法在可用的條目中搜索IP地址對應的名稱,同時在沒有條目可以提供和IP地址匹配的名稱時丟擲 CertificateException 異常
    所以,如果想通過使用 IP 作為主機名連線,證書中應該包含名稱和與其匹配的 IP 地址這個條目