调用第三方接口报错ssl证书相关错误问题解决方案

本文介绍了一种使用HttpClient调用HTTPS接口时遇到的SSL证书错误,并提供了解决方案,包括如何忽略证书验证。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这是本人开通账号后的第一篇文章,平时上班比较忙没有多余的时间来写博客,今天难得闲下来统计下前两天遇到的一个问题以及我的处理方式。

事情发生在2天前,我使用httpclient调用第三方接口时,没有注意第三方接口是https的,众所周知httpClient是不能直接调用https的,直接调用会报SSL证书相关错误,刚开始呢没注意是我的工具类的问题,提示我没有信任该域名的证书,于是我把域名对应的证书下载下来添加到了本地的jre信任中去,解决了这个问题。可以参考以下的链接:

彻底解决unable to find valid certification path to requested target - 进击的Ace - 博客园

        现在问题是解决了,接口也调通了,但新的问题又来了,我是要发布在测试环境进行测试的,测试通过后还要部署在正式环境上去,现在这样操作岂不是两边的服务器我都要添加jre信任才行吗?也是直到这个时候我才发现原来是我的工具类是httpClient调用的原因,附上我的工具类~

        如下:

import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

import java.io.IOException;

public class HttpClientUtil {

    public static String doPostJson(String url, String json) {
        CloseableHttpClient httpClient = HttpClients.createDefault();
        CloseableHttpResponse response = null;
        String resultString = "";
        try {
            HttpPost httpPost = new HttpPost(url);
            StringEntity entity = new StringEntity(json, ContentType.APPLICATION_JSON);
            httpPost.setEntity(entity);
            response = httpClient.execute(httpPost);
            resultString = EntityUtils.toString(response.getEntity(), "utf-8");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                response.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        return resultString;
    }
    
}

         此时就有了好的解决方案,直接换一个工具类就行,但是如果说我非要使用httpClient工具类调用https的第三方接口该怎么处理呢?是否有相关的代码或者httpClient工具类的工具类让它去调用的时候忽略证书或者是自动添加信任呢?于是开始在网上疯狂找资料向同事大神请教,还真被我找到了.

        代码如下:

import org.apache.http.conn.ClientConnectionManager;
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 javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

public class SSLClient extends DefaultHttpClient {

    public SSLClient() throws Exception{
        super();
        SSLContext ctx = SSLContext.getInstance("TLS");
        X509TrustManager tm = 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 null;
            }
        };
        ctx.init(null, new TrustManager[]{tm}, null);
        SSLSocketFactory ssf = new SSLSocketFactory(ctx,SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
        ClientConnectionManager ccm = this.getConnectionManager();
        SchemeRegistry sr = ccm.getSchemeRegistry();
        sr.register(new Scheme("https", 443, ssf));
    }

}

按照我和我同事大神钻(hu)研(shuo)得(ba)出(dao),这个工具类可以让我们使用httpClient工具类调用https接口时忽略证书,或者说不去验证证书。于是我修改了下我的httpClient工具类,附图~

        代码如下:

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicHeader;
import org.apache.http.util.EntityUtils;

import java.io.IOException;

public class HttpClientUtil {

    public static String doPostJson(String url, String json) {
        CloseableHttpClient httpClient = HttpClients.createDefault();
        CloseableHttpResponse response = null;
        String resultString = "";
        try {
            HttpPost httpPost = new HttpPost(url);
            StringEntity entity = new StringEntity(json, ContentType.APPLICATION_JSON);
            httpPost.setEntity(entity);
            response = httpClient.execute(httpPost);
            resultString = EntityUtils.toString(response.getEntity(), "utf-8");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                response.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        return resultString;
    }
    public static String doPost(String url,String jsonstr){
        HttpClient httpClient = null;
        HttpPost httpPost = null;
        String result = null;
        try{
            httpClient = new SSLClient();
            httpPost = new HttpPost(url);
            httpPost.addHeader("Content-Type", "application/json");
            if(jsonstr != null){
                StringEntity se = new StringEntity(jsonstr);
                se.setContentType("text/json");
                se.setContentEncoding(new BasicHeader("Content-Type", "application/json"));
                httpPost.setEntity(se);
            }
            HttpResponse response = httpClient.execute(httpPost);
            if(response != null){
                HttpEntity resEntity = response.getEntity();
                if(resEntity != null){
                    result = EntityUtils.toString(resEntity,"UTF-8");
                }
            }
        }catch(Exception ex){
            ex.printStackTrace();
        }
        return result;
    }
}

         之前调用的是httpclient.doPostJson方法,修改后直接调用.doPost方法,本地测试和在生产环境都没问题,完美解决~

        不知道这种方法会不会存在弊端,欢迎各位前辈在评论区指出错误。

          PS:这种方法仅适用于强迫症程序员,正常调用还请另使用RestTemplate相关模板~

### 如何解决运行代码时出现的SSL错误 当遇到 SSL 错误时,通常是因为客户端与服务器之间的加密通信出现问题。这类问题可能源于证书验证失败、协议版本不兼容或是本地环境配置不当等原因。 对于 PHP 中通过 Composer 发生的 SSL 报错情况,建议检查并调整 `php.ini` 文件中的 SSL 设置[^1]: ```ini ; 启用 OpenSSL 支持 extension=openssl.so ; 对于 Linux/MacOS 用户 extension=php_openssl.dll ; 对于 Windows 用户 ; 如果需要忽略 SSL 证书校验(仅用于开发环境) openssl.cafile=/path/to/cert.pem ``` 针对 Python 环境下发生的 SSL 认证错误,特别是像 `SSLCertVerificationError` 这样的特定异常,在安装第三方库或执行网络请求时可能会碰到。一种常见的解决方案是在项目根目录放置 cacert.pem 文件,并将其路径告知 Python 的 SSL 模块;另一种方式则是临时关闭认证过程,但这并不推荐应用于生产环境中[^2]: ```python import os import ssl # 方法一:指定 CA 根证书位置 os.environ['SSL_CERT_FILE'] = '/usr/local/etc/ssl/certs/ca-certificates.crt' # 或者使用 create_default_context 并加载默认系统CA列表 context = ssl.create_default_context(cafile="/etc/pki/tls/certs/ca-bundle.crt") # 方法二:跳过证书验证 (仅供测试用途!) context = ssl._create_unverified_context() ``` 如果问题是由于操作系统层面的安全策略所引起的,则需考虑更新系统的安全补丁或者按照官方文档指导来修正相应的注册表项或其他配置选项。例如,在某些情况下,Windows Server 可能会因为未开启更高版本的传输层安全性(TLS)而导致应用程序无法正常工作。此时应当参照微软的支持文章启用 TLS 1.2 协议支持[^3]。 最后,关于 Gevent 库引发的 `MonkeyPatchWarning` 警告信息,这通常是由于在导入其他依赖之前就已经对标准库进行了猴子补丁操作所致。为了避免此类警告的发生,应该确保所有的 monkey patching 行为都发生在任何实际业务逻辑之前的最早阶段,即尽可能早地调用 `gevent.monkey.patch_all()` 函数[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值