最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

一文解決Java中IP地址訪問HTTPS接口的SSL證書驗(yàn)證問題

 更新時(shí)間:2025年12月19日 08:33:05   作者:一勺菠蘿丶  
這篇文章主要為大家詳細(xì)介紹了解決Java中IP地址訪問HTTPS接口的SSL證書驗(yàn)證問題的相關(guān)知識(shí),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解下

問題描述

在使用Java的RestTemplate訪問HTTPS接口時(shí),如果使用IP地址而不是域名,經(jīng)常會(huì)遇到以下錯(cuò)誤:

java.security.cert.CertificateException: No subject alternative names matching IP address 111.63.81.79 found
nested exception is javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No subject alternative names matching IP address 111.63.81.79 found

奇怪的是:使用Postman、curl等工具可以正常訪問,但Java代碼卻報(bào)錯(cuò)。

問題原因

SSL證書驗(yàn)證機(jī)制

HTTPS協(xié)議在建立連接時(shí),會(huì)進(jìn)行SSL證書驗(yàn)證,主要包括兩個(gè)方面:

  • 證書有效性驗(yàn)證:檢查證書是否過期、是否被吊銷等
  • 主機(jī)名驗(yàn)證:檢查證書中的域名或IP地址是否與訪問的地址匹配

為什么Postman可以,Java不行

  • Postman:默認(rèn)情況下,Postman可能會(huì)跳過某些SSL驗(yàn)證(特別是開發(fā)環(huán)境)
  • Java:Java的SSL驗(yàn)證非常嚴(yán)格,會(huì)檢查證書的Subject Alternative Names (SAN)字段
  • 問題根源:當(dāng)使用IP地址訪問時(shí),如果證書的SAN中沒有包含該IP地址,Java就會(huì)拒絕連接

證書的Subject Alternative Names

SSL證書中有一個(gè)字段叫Subject Alternative Names (SAN),它列出了該證書可以用于哪些域名或IP地址。例如:

Subject Alternative Names:
    DNS: example.com
    DNS: www.example.com
    IP Address: 192.168.1.1

如果證書中沒有包含你訪問的IP地址(如111.63.81.79),Java就會(huì)拋出上述異常。

解決方案

方案概述

我們需要配置RestTemplate,讓它跳過SSL證書驗(yàn)證。注意:這種方法只適用于開發(fā)/測(cè)試環(huán)境,生產(chǎn)環(huán)境應(yīng)該使用正確的證書。

完整代碼實(shí)現(xiàn)

創(chuàng)建一個(gè)RestTemplateConfig配置類:

package com.example.zbx.config;

import org.apache.http.client.config.RequestConfig;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.security.cert.X509Certificate;

/**
 * RestTemplate配置類
 * 配置忽略SSL證書驗(yàn)證,支持使用IP地址訪問HTTPS接口
 * @author lxy
 */
@Configuration
public class RestTemplateConfig {

    /**
     * 創(chuàng)建RestTemplate Bean
     * 配置忽略SSL證書驗(yàn)證,支持使用IP地址訪問HTTPS接口
     * @return RestTemplate實(shí)例
     */
    @Bean
    public RestTemplate restTemplate() {
        try {
            // 創(chuàng)建完全信任所有證書的TrustManager
            TrustManager[] trustAllCerts = new TrustManager[]{
                    new X509TrustManager() {
                        @Override
                        public X509Certificate[] getAcceptedIssuers() {
                            return null;
                        }

                        @Override
                        public void checkClientTrusted(X509Certificate[] certs, String authType) {
                            // 不進(jìn)行任何檢查,信任所有客戶端證書
                        }

                        @Override
                        public void checkServerTrusted(X509Certificate[] certs, String authType) {
                            // 不進(jìn)行任何檢查,信任所有服務(wù)器證書
                        }
                    }
            };

            // 創(chuàng)建SSL上下文,使用自定義的TrustManager
            SSLContext sslContext = SSLContext.getInstance("TLS");
            sslContext.init(null, trustAllCerts, new java.security.SecureRandom());

            // 創(chuàng)建SSL連接工廠,忽略主機(jī)名驗(yàn)證(包括IP地址驗(yàn)證)
            SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(
                    sslContext,
                    NoopHostnameVerifier.INSTANCE
            );

            // 創(chuàng)建請(qǐng)求配置
            RequestConfig requestConfig = RequestConfig.custom()
                    .setConnectTimeout(10000)  // 連接超時(shí)10秒
                    .setConnectionRequestTimeout(10000)  // 請(qǐng)求超時(shí)10秒
                    .setSocketTimeout(30000)  // 讀取超時(shí)30秒
                    .build();

            // 創(chuàng)建HttpClient
            CloseableHttpClient httpClient = HttpClients.custom()
                    .setSSLSocketFactory(sslSocketFactory)
                    .setDefaultRequestConfig(requestConfig)
                    .evictExpiredConnections()
                    .evictIdleConnections(30, java.util.concurrent.TimeUnit.SECONDS)
                    .build();

            // 創(chuàng)建請(qǐng)求工廠
            HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
            factory.setHttpClient(httpClient);
            factory.setConnectTimeout(10000);
            factory.setConnectionRequestTimeout(10000);
            factory.setReadTimeout(30000);

            // 創(chuàng)建RestTemplate
            return new RestTemplate(factory);
        } catch (Exception e) {
            throw new RuntimeException("創(chuàng)建RestTemplate失敗", e);
        }
    }
}

關(guān)鍵點(diǎn)說明

1. 自定義TrustManager

TrustManager[] trustAllCerts = new TrustManager[]{
    new X509TrustManager() {
        @Override
        public void checkServerTrusted(X509Certificate[] certs, String authType) {
            // 不進(jìn)行任何檢查,信任所有服務(wù)器證書
        }
        // ... 其他方法
    }
};

這個(gè)X509TrustManager會(huì)跳過所有證書驗(yàn)證,包括:

  • 證書是否過期
  • 證書是否被吊銷
  • 證書的域名/IP是否匹配

2. 創(chuàng)建SSL上下文

SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, trustAllCerts, new java.security.SecureRandom());

使用自定義的TrustManager初始化SSL上下文。

3. 忽略主機(jī)名驗(yàn)證

SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(
    sslContext,
    NoopHostnameVerifier.INSTANCE  // 不驗(yàn)證主機(jī)名
);

NoopHostnameVerifier.INSTANCE會(huì)跳過主機(jī)名驗(yàn)證,這樣即使證書中沒有對(duì)應(yīng)的IP地址也能通過驗(yàn)證。

Maven依賴

確保你的pom.xml中包含以下依賴:

<!-- HttpClient4 (for RestTemplate SSL configuration) -->
<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
</dependency>

使用示例

配置完成后,直接使用RestTemplate即可,無需額外代碼:

@Autowired
private RestTemplate restTemplate;

public void callApi() {
    String url = "https://111.63.81.79:10091/api/endpoint";
    ResponseEntity<String> response = restTemplate.postForEntity(url, request, String.class);
    // 處理響應(yīng)...
}

注意事項(xiàng)

安全警告

  • 僅用于開發(fā)/測(cè)試環(huán)境:跳過SSL驗(yàn)證會(huì)帶來安全風(fēng)險(xiǎn),生產(chǎn)環(huán)境不應(yīng)該使用
  • 中間人攻擊風(fēng)險(xiǎn):攻擊者可以偽造證書,你的應(yīng)用無法識(shí)別
  • 數(shù)據(jù)泄露風(fēng)險(xiǎn):無法保證連接的安全性

生產(chǎn)環(huán)境建議

如果必須在生產(chǎn)環(huán)境使用,建議:

  • 使用正確的證書:讓服務(wù)器提供包含IP地址的證書
  • 配置證書信任:只信任特定的證書頒發(fā)機(jī)構(gòu)(CA)
  • 使用域名訪問:盡量使用域名而不是IP地址

示例:生產(chǎn)環(huán)境的正確做法

// 只信任特定的證書
KeyStore trustStore = KeyStore.getInstance("JKS");
trustStore.load(new FileInputStream("truststore.jks"), "password".toCharArray());

TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("X509");
trustManagerFactory.init(trustStore);

SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, trustManagerFactory.getTrustManagers(), null);

常見問題

Q1: 為什么之前可以,現(xiàn)在不行了?

可能的原因:

  • Java版本更新,SSL驗(yàn)證更嚴(yán)格了
  • 服務(wù)器證書更新了,新證書沒有包含IP地址
  • 網(wǎng)絡(luò)環(huán)境變化,使用了不同的IP地址

Q2: 有沒有更簡單的辦法?

對(duì)于開發(fā)環(huán)境,可以設(shè)置JVM參數(shù)(不推薦):

-Dcom.sun.net.ssl.checkRevocation=false

但這種方法不夠靈活,建議使用配置類的方式。

Q3: 會(huì)影響其他HTTP請(qǐng)求嗎?

不會(huì)。這個(gè)配置只影響使用RestTemplate的HTTPS請(qǐng)求,HTTP請(qǐng)求不受影響。

Q4: 如何驗(yàn)證配置是否生效?

在代碼中添加日志,觀察是否還有證書驗(yàn)證錯(cuò)誤:

log.info("RestTemplate配置完成,SSL驗(yàn)證已禁用");

如果不再出現(xiàn)CertificateException,說明配置生效了。

總結(jié)

  • 問題根源:Java的SSL驗(yàn)證嚴(yán)格,證書中沒有IP地址時(shí)會(huì)拒絕連接
  • 解決方案:配置RestTemplate跳過SSL證書驗(yàn)證
  • 關(guān)鍵代碼:自定義X509TrustManager + NoopHostnameVerifier
  • 安全提醒:僅用于開發(fā)/測(cè)試環(huán)境,生產(chǎn)環(huán)境應(yīng)使用正確的證書

到此這篇關(guān)于一文解決Java中IP地址訪問HTTPS接口的SSL證書驗(yàn)證問題的文章就介紹到這了,更多相關(guān)Java解決SSL證書驗(yàn)證問題內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Mybatis遷移到Mybatis-Plus的實(shí)現(xiàn)方法

    Mybatis遷移到Mybatis-Plus的實(shí)現(xiàn)方法

    這篇文章主要介紹了Mybatis遷移到Mybatis-Plus的實(shí)現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-08-08
  • 如何基于LoadingCache實(shí)現(xiàn)Java本地緩存

    如何基于LoadingCache實(shí)現(xiàn)Java本地緩存

    這篇文章主要介紹了如何基于LoadingCache實(shí)現(xiàn)Java本地緩存,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-12-12
  • idea本地merge如何合并代碼

    idea本地merge如何合并代碼

    這篇文章主要介紹了idea本地merge如何合并代碼問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-06-06
  • Java從控制臺(tái)接受輸入字符的簡單方法

    Java從控制臺(tái)接受輸入字符的簡單方法

    這篇文章主要介紹了Java從控制臺(tái)接受輸入字符的簡單方法,需要的朋友可以參考下
    2014-02-02
  • SpringBoot如何接收前端傳遞參數(shù)

    SpringBoot如何接收前端傳遞參數(shù)

    這篇文章主要介紹了SpringBoot如何接收前端傳遞參數(shù),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2024-08-08
  • Java壓縮文件為ZIP并加密的詳細(xì)步驟

    Java壓縮文件為ZIP并加密的詳細(xì)步驟

    Zip是一種常用的文件壓縮格式,下面這篇文章主要給大家介紹了關(guān)于Java壓縮文件為ZIP并加密的詳細(xì)步驟,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-11-11
  • Java平閏年判斷的方法總結(jié)

    Java平閏年判斷的方法總結(jié)

    本篇文章給大家整理了Java平閏年判斷的兩種方法,大家在寫程序的時(shí)候如果用的到參考下吧。
    2018-02-02
  • Java中跨域問題解決的幾種方式舉例詳解

    Java中跨域問題解決的幾種方式舉例詳解

    這篇文章主要介紹了前后端分離項(xiàng)目中跨域問題的解決方法,包括設(shè)置響應(yīng)頭信息、使用iframe、WebSocket、HttpServletResponse添加頭信息以及通過配置類等多種方式,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-12-12
  • EditPlus運(yùn)行java時(shí)從鍵盤輸入數(shù)據(jù)的操作方法

    EditPlus運(yùn)行java時(shí)從鍵盤輸入數(shù)據(jù)的操作方法

    這篇文章主要介紹了EditPlus運(yùn)行java時(shí)從鍵盤輸入數(shù)據(jù)的操作方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-03-03
  • Java中的static關(guān)鍵字用法總結(jié)

    Java中的static關(guān)鍵字用法總結(jié)

    這篇文章主要介紹了Java中的static關(guān)鍵字用法總結(jié),static是Java50個(gè)關(guān)鍵字之一,static關(guān)鍵字可以用來修飾代碼塊表示靜態(tài)代碼塊,修飾成員變量表示全局靜態(tài)成員變量,修飾方法表示靜態(tài)方法,需要的朋友可以參考下
    2023-11-11

最新評(píng)論

邳州市| 四子王旗| 栾川县| 高邑县| 天水市| 女性| 无棣县| 汉源县| 蓝山县| 平塘县| 盐津县| 溧阳市| 安远县| 靖安县| 城步| 永嘉县| 沙坪坝区| 桐乡市| 阳高县| 咸宁市| 汉中市| 鹰潭市| 稻城县| 江口县| 隆回县| 甘泉县| 玉林市| 客服| 白山市| 伊宁县| 博野县| 迭部县| 图木舒克市| 唐河县| 泗洪县| 白沙| 双牌县| 四平市| 溆浦县| 盐源县| 平利县|