• 解决Java中https请求接口报错问题


    1. 解决SSLException: Certificate for <域名> doesn‘t match any of the subject alternative报错问题

    1.1 问题描述

    最近在做一个智能问答客服项目,对接的是云问接口,然后云问接口对接使用的是https方式,之前一直是http方式,突然的改变,使得项目访问报错。报错信息如标题所示。就是SSL证书的问题。

    1.2 解决方案

    第一种解决方案:

    遇到问题首先debug一下,发现是在项目中的一个工具类中引起的报错,好像是因为没有规定使用默认证书之类的吧,不知道理解的对不对,反正根据下面的代码改了之后就可以了,但是还是会有一些其它的问题,具体可以往下看。

    在之前的代码上,也就是发送http请求的代码那里,增加下面两条语句。作用主要是配置带有SSL/TSL安全连接的HttpClient。

    SSLConnectionSocketFactory scsf = new SSLConnectionSocketFactory(SSLContexts.custom().loadTrustMaterial(null, new TrustSelfSignedStrategy()).build(), NoopHostnameVerifier.INSTANCE);
    httpclient = HttpClients.custom().setSSLSocketFactory(scsf).build();
    
    • 1
    • 2

    修正之后的代码如下:

    public static String doGet(String url, Map<String, Object> params) throws IOException {  
            String apiUrl = url;  
            StringBuffer param = new StringBuffer();  
            int i = 0;  
            for (String key : params.keySet()) {  
                if (i == 0)  
                    param.append("?");  
                else  
                    param.append("&");  
                param.append(key).append("=").append(params.get(key));  
                i++;  
            }  
            apiUrl += param;  
            String result = null;  
            CloseableHttpClient httpclient = HttpClients.createDefault();
            try {
                SSLConnectionSocketFactory scsf = new SSLConnectionSocketFactory(SSLContexts.custom().loadTrustMaterial(null, new TrustSelfSignedStrategy()).build(), NoopHostnameVerifier.INSTANCE);
                httpclient = HttpClients.custom().setSSLSocketFactory(scsf).build();
    
                HttpGet httpPost = new HttpGet(apiUrl);  
                HttpResponse response = httpclient.execute(httpPost);
    
                HttpEntity entity = response.getEntity();  
                if (entity != null) {  
                    InputStream instream = entity.getContent();  
                    result = IOUtils.toString(instream, "UTF-8");  
                }  
            } catch (Exception e) {  
                e.printStackTrace();  
            }
            } finally {
            	if(httpclient!=null) {
            		httpclient.close();
            	}
            }
            return result;  
        }  
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    第二种解决方案:

    这种解决方案是ChatGPT给的,我没有验证其正确性。

    import org.apache.http.client.HttpClient;
    import org.apache.http.client.methods.HttpGet;
    import org.apache.http.client.methods.CloseableHttpResponse;
    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.apache.http.ssl.SSLContextBuilder;
    
    import javax.net.ssl.SSLContext;
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    
    public class HTTPSRequestExample {
        public static void main(String[] args) {
            try {
                // 创建自定义SSLContext
                SSLContext sslContext = SSLContextBuilder.create().loadTrustMaterial((chain, authType) -> true).build();
    
                // 创建SSLConnectionSocketFactory并禁用主机名验证
                SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE);
    
                // 使用自定义SSLConnectionSocketFactory创建HttpClient
                CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(sslSocketFactory).build();
    
                // 创建要发送的GET请求
                HttpGet request = new HttpGet("https://example.com");
    
                // 发送请求并获取响应
                CloseableHttpResponse response = httpClient.execute(request);
    
                // 读取响应内容
                BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
                String line;
                StringBuilder content = new StringBuilder();
                while ((line = reader.readLine()) != null) {
                    content.append(line);
                }
    
                // 输出响应内容
                System.out.println("Response Content: " + content.toString());
    
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (response != null) {
                    response.close();
                }
                if (httpClient != null) {
                    httpClient.close();
                }
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56

    1.3 参考文献

    stackoverflow参考文档

    CSDN参考文档

    2. 出现新问题

    根据上面的修改代码后,又会出现新的问题,图片,音频,视频似乎不行,f12看控制台会有报错,好像是与证书相关的报错,同时也会改变请求的路径为本地路径。如下图所示的报错。

    image-20231106114630319

  • 相关阅读:
    AJAX学习(一)
    Cookie与Session的区别
    MySQL 索引详解
    X86与FPGA相结合,基于PIB的AI开发——人体姿态识别
    JavaSE——学习总结
    基础矩阵和本质矩阵
    css之 vertical-align用法详解
    已解决:一个表中可以有多个自增列吗
    改善机器视觉系统的方法
    基于Mxnet实现目标跟踪SMOT【附部分源码】
  • 原文地址:https://blog.csdn.net/qq_43907505/article/details/134258974