编辑代码

package org.linxidev.utils;

import java.net.URL;
import java.util.Map;
import java.util.HashMap;
import java.io.OutputStream;
import java.io.BufferedReader;
import javax.net.ssl.SSLContext;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import javax.net.ssl.TrustManager;
import com.alibaba.fastjson2.JSON;
import javax.net.ssl.X509TrustManager;
import javax.net.ssl.HttpsURLConnection;
import com.alibaba.fastjson2.JSONObject;
import java.nio.charset.StandardCharsets;
import java.security.cert.X509Certificate;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;

/**
 * Created with IntelliJ IDEA.
 *
 * @Author: 林夕
 * @Date: 2024/11/25
 * @Description: HTTP/HTTPS 请求工具类
 */

public class HttpsUtils {

    /**
     * JSON对象转字符串
     */
    public static String jsonParse(JSONObject json) { return JSON.toJSONString(json); }

    /**
     * JSON字符串转JSON对象
     */
    public static JSONObject jsonFormat(String json) { return JSONObject.parseObject(json); }

    /**
     * 将传入的JSON格式的 params 参数转为URL参数
     */
    public static String paramsToUrl(String params) {
        if (params == null) { return ""; }
        JSONObject paramsMap = jsonFormat(params);
        StringBuilder sb = new StringBuilder("?");
        for (Map.Entry<String, Object> entry : paramsMap.entrySet()) {
            sb.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
        }
        // 去除末尾的 &
        if (sb.length() > 0) { sb.setLength(sb.length() - 1); }
        return sb.toString();
    }

    /**
     * HTTPS 请求忽略SSL证书
     */
    private static void sslCert(HttpURLConnection con, boolean cert) throws NoSuchAlgorithmException, KeyManagementException {
        if (con instanceof HttpsURLConnection) {
            if (cert) {
                // 设置默认的SSL上下文和主机名验证器
                SSLContext defaultSslContext = SSLContext.getDefault();
                if (defaultSslContext == null) {
                    defaultSslContext = SSLContext.getInstance("TLS");
                    defaultSslContext.init(null, null, null);
                }
                ((HttpsURLConnection) con).setSSLSocketFactory(defaultSslContext.getSocketFactory());
                ((HttpsURLConnection) con).setHostnameVerifier((hostname, session) -> hostname.equalsIgnoreCase(con.getURL().getHost()));
                System.out.println("[\033[33mWarning\033[0m] SSL Certificate Verification Enabled");
            } else {
                // 忽略证书验证
                TrustManager[] trustAllCerts = new TrustManager[]{
                        new X509TrustManager() {
                            @Override
                            public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; }
                            @Override
                            public void checkClientTrusted(X509Certificate[] certs, String authType) {}
                            @Override
                            public void checkServerTrusted(X509Certificate[] certs, String authType) {}
                        }
                };
                SSLContext sslContext = SSLContext.getInstance("SSL");
                sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
                ((HttpsURLConnection) con).setSSLSocketFactory(sslContext.getSocketFactory());
                ((HttpsURLConnection) con).setHostnameVerifier((hostname, session) -> true);
                System.out.println("[\033[33mWarning\033[0m] SSL Certificate Verification Disabled");
            }
        }
    }

    /**
     * 发送GET请求(HTTP、HTTPS) 默认方法
     * @param url 请求的URL
     * @return 返回请求结果
     */
    public static String urlSend(String url) throws Exception { return urlSend(url,"GET"); }

    /**
     * 发送GET、POST请求(HTTP、HTTPS) 自定义请求方法
     * @param url 请求的URL
     * @return 返回请求结果
     */
    public static String urlSend(String url, String method) throws Exception { return urlSend(url, method,false); }

    /**
     * 发送GET、POST请求(HTTP、HTTPS) 自定义请求方法和是否忽略证书验证
     * @param url 请求的URL
     * @param method 请求方法
     * @param cert 是否使用证书验证 (true:忽略证书,false:使用证书)
     * @return 返回请求结果
     */
    public static String urlSend(String url, String method, boolean cert) throws Exception {
        Map<String, String> headers = new HashMap<>();
        headers.put("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36");
        headers.put("Accept", "*/*");
        headers.put("Content-Type", "application/x-www-form-urlencoded");
        return urlSend(url, method, cert, null, headers);
    }

    /**
     * 发送GET、POST请求(HTTP、HTTPS) 自定义请求方法和是否忽略证书验证和提交参数
     * @param url 请求的URL
     * @param method 请求方法
     * @param cert 是否使用证书验证 (true:忽略证书,false:使用证书)
     * @return 返回请求结果
     */
    public static String urlSend(String url, String method, boolean cert,String data) throws Exception {
        Map<String, String> headers = new HashMap<>();
        headers.put("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36");
        headers.put("Accept", "*/*");
        headers.put("Content-Type", "application/x-www-form-urlencoded");
        return urlSend(url, method, cert, data, headers);
    }

    /**
     * 发送GET、POST请求(HTTP、HTTPS)
     * @param url 请求的URL
     * @param method 请求方法
     * @param cert 是否使用证书验证 (true:忽略证书,false:使用证书)
     * @param data 请求参数
     * @param headers 请求头
     * @return 返回请求结果
     */
    public static String urlSend(String url, String method, boolean cert, String data, Map<String, String> headers) throws Exception {
        if ("GET".equals(method)){url = url + paramsToUrl(data);}
        URL obj = new URL(url);
        HttpURLConnection con = (HttpURLConnection) obj.openConnection();
        // 忽略证书、验证证书
        sslCert(con, cert);
        // 设置请求方法
        con.setRequestMethod(method);
        // 添加请求头
        if (headers != null) {
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                con.setRequestProperty(entry.getKey(), entry.getValue());
            }
        }
        if ("POST".equals(method)){
            con.setDoOutput(true);
            // 写入请求参数
            if (data != null) {
                try (OutputStream os = con.getOutputStream()) {
                    byte[] input = data.getBytes(StandardCharsets.UTF_8);
                    os.write(input, 0, input.length);
                }catch (Exception e){
                    System.out.println("[\033[31m Error \033[0m] URL:" + url + " FAIL:" + e.getMessage());
                    return "";
                }finally {
                    con.disconnect();
                }
            }
        }
        try {
            // 读取响应码
            int code = con.getResponseCode();
            // 读取响应
            StringBuilder response = new StringBuilder();
            try (BufferedReader in = new BufferedReader(new InputStreamReader((code >= 200 && code < 300) ? con.getInputStream() : con.getErrorStream()))) {
                String inputLine;
                while ((inputLine = in.readLine()) != null) {
                    response.append(inputLine);
                }
                System.out.println("[\033[32mSuccess\033[0m] Code:" + code + " Response:" + response);
                return response.toString();
            } catch (Exception e) {
                System.out.println("[\033[31m Error \033[0m] Code:" + code + " Response:" + e.getMessage());
                return "";
            }
        }catch (Exception e){
            System.out.println("[\033[31m Error \033[0m] " + e.getMessage());
            return "";
        }finally {
            // 断开连接
            con.disconnect();
        }
    }

    /**
     * 测试方法 用于测试证书验证和忽略证书
     * @Author: 林夕
     * @Date: 2023/9/27 15:09
     * @Description: 可以手动导出证书后导入到Java进行测试
     * 导入证书: keytool -keystore %JAVA_HOME%/lib/security/cacerts -importcert -alias 别名 -file 证书文件 -storepass changeit
     * 删除证书: keytool -keystore %JAVA_HOME%/lib/security/cacerts -delete -alias 别名 -storepass changeit
     * 查询证书: keytool -keystore %JAVA_HOME%/lib/security/cacerts -list -v -alias 别名 -storepass changeit
     */
    public static void main(String[] args) {
        try {
            String response;
            // 测试HTTP GET连接
            response = HttpsUtils.urlSend("http://blog.xxxx.tk");
            System.out.println("HTTP GET Response: " + response);

            // 测试HTTPS GET连接,使用证书验证
            response = HttpsUtils.urlSend("https://blog.xxxx.tk", "GET",true);
            System.out.println("HTTPS GET (Cert) Response: " + response);

            // 测试HTTPS GET连接,忽略证书
            response = HttpsUtils.urlSend("https://blog.xxxx.tk", "GET");
            System.out.println("HTTPS GET (No Cert) Response: " + response);

            // 测试HTTP POST连接
            response = HttpsUtils.urlSend("http://blog.xxxx.tk", "POST");
            System.out.println("HTTP POST Response: " + response);

            // 测试HTTPS POST连接,使用证书验证
            response = HttpsUtils.urlSend("https://blog.xxxx.tk", "POST",true);
            System.out.println("HTTPS POST (Cert) Response: " + response);

            // 测试HTTPS POST连接,忽略证书
            response = HttpsUtils.urlSend("https://blog.xxxx.tk", "POST");
            System.out.println("HTTPS POST (No Cert) Response: " + response);

            // 测试POST参数 DATA
            response = HttpsUtils.urlSend("http://so.studypro.club/api/search", "POST",false,"question=今天&phone=");
            System.out.println("DATA Response: " + response);

            // 测试POST参数 JSON
            Map<String, String> headers = new HashMap<>();
            headers.put("Content-Type", "application/json");
            response = HttpsUtils.urlSend("http://so.studypro.club/api/search", "POST",false, "{\"question\": \"今天\",\"phone\":\"\"}", headers);
            System.out.println("JSON Response: " + response);

            // 测试POST参数 SOAP(XML)
            headers = new HashMap<>();
            headers.put("Content-Type", "text/xml; charset=utf-8");
            headers.put("SOAPAction", "http://WebXml.com.cn/getAreaDataSet");
            response = HttpsUtils.urlSend("http://ws.webxml.com.cn/webservices/ChinaTVprogramWebService.asmx", "POST",false,"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
                    "<soap12:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap12=\"http://www.w3.org/2003/05/soap-envelope\">\n" +
                    "  <soap12:Body>\n" +
                    "    <getAreaDataSet xmlns=\"http://WebXml.com.cn/\" />\n" +
                    "  </soap12:Body>\n" +
                    "</soap12:Envelope>",headers);
            System.out.println("SOAP Response: " + response);

            // 测试JSON 解析
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("name", "LineX");
            jsonObject.put("age", 18);
            System.out.println(HttpsUtils.jsonParse(jsonObject));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}