在Springboot项目部署时遇到,centos服务器上,curl请求目标地址不通 ,curl -x 可以请求通的解决办法

在甲方服务器部署项目时,通常遇到需要开通外网权限的问题,有的是直接给开通服务器的白名单,就可以直接访问白名单外网地址了。也有的是通过网络转发,将url前面的部分替换,可以进行网络请求。有一次遇到一个罕见的,对方应是使用squid进行代理的。直接curl外网地址是不通的,使用curl -x 代理服务器ip:端口 目标地址可以访问通。针对此种场景,测试了以下配置代方法

1. 全局环境变量配置

在centos中配置当前用户或者全局环境变量,是可行的,配置完成后,curl命令后不用-x就可以直接访问了。但是这种方法,本服务器上部署的java和nginx确是无效的

# 编辑配置文件vim ~/.bashrc # 或 ~/.bash_profile 
# 添加以下内容(替换为您的代理服务器信息) 
export http_proxy=http://10.10.10.61:8080 
export https_proxy=http://10.10.10.61:8080 
# 设置 NO_PROXY 变量,指定哪些域名不需要通过代理(逗号分隔,支持通配符) 
export no_proxy="localhost,127.0.0.1,192.168.1.0/24,.example.com" 
# 使配置生效 
source ~/.bashrc

2. springboot web服务内,httpClient配置

在使用1中的方法,配置环境变量后,发现使用Springboot服务请求时,还是不通。提示域名无法解析。

使用了网上的方法,在启动jar包时,配置如下的启动参数或者环境变量依然无效。

java -Dhttp.proxyHost=10.20.102.61 -Dhttp.proxyPort=8080 -Dhttps.proxyHost=10.20.102.61 -Dhttps.proxyPort=8080  -Dsun.net.spi.nameservice.provider.1=dns,sun -Djava.net.preferIPv4Stack=true -jar

最后使用了在代码里统一配置httpClient的方式实现

依赖

        <dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId><version>4.5.13</version></dependency>
  • HttpProxyClientUtil.java
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
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.message.BasicNameValuePair;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.util.EntityUtils;import javax.net.ssl.SSLContext;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;/*** Apache HttpClient 4.x 实现的 HTTP 请求工具类(支持代理、SSL 绕过、多种请求体)*/
public class HttpProxyClientUtil {// -------------------- 基础配置 --------------------// 连接超时(毫秒)private static final int CONNECT_TIMEOUT = 5000;// 读取超时(毫秒)private static final int READ_TIMEOUT = 5000;// -------------------- 代理配置 --------------------// 代理主机(需替换为实际代理 IP/域名)private static final String PROXY_HOST = "10.10.10.61";// 代理端口(需替换为实际代理端口)private static final int PROXY_PORT = 8080;// -------------------- 构建 HttpClient(支持代理、SSL 绕过) --------------------public static CloseableHttpClient createHttpClient(boolean ignoreSsl) {try {// 1. 构建 SSL 上下文(可选:绕过证书校验)SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, (chain, authType) -> true) // 信任所有证书.build();SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(sslContext,NoopHostnameVerifier.INSTANCE // 跳过主机名校验);// 2. 构建请求配置(含代理)RequestConfig.Builder requestConfigBuilder = RequestConfig.custom().setConnectTimeout(CONNECT_TIMEOUT).setSocketTimeout(READ_TIMEOUT).setProxy(new org.apache.http.HttpHost(PROXY_HOST, PROXY_PORT)); // 设置代理// 3. 构建 HttpClientCloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(ignoreSsl? sslSocketFactory : SSLConnectionSocketFactory.getSystemSocketFactory()).setDefaultRequestConfig(requestConfigBuilder.build()).build();return httpClient;} catch (NoSuchAlgorithmException | KeyManagementException | KeyStoreException e) {throw new RuntimeException("构建 HttpClient 失败", e);}}// -------------------- GET 请求 --------------------/*** 发送 GET 请求(支持代理、SSL 绕过)* @param url       请求地址* @param ignoreSsl 是否忽略 SSL 证书校验(生产环境慎用)* @return 响应内容(字符串)*/public static String doGet(String url, boolean ignoreSsl) {CloseableHttpClient httpClient = createHttpClient(ignoreSsl);HttpGet httpGet = new HttpGet(url);// 可在此处添加请求头(示例)httpGet.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)");try (CloseableHttpResponse response = httpClient.execute(httpGet)) {HttpEntity entity = response.getEntity();if (entity != null) {return EntityUtils.toString(entity, StandardCharsets.UTF_8);}return "";} catch (IOException e) {throw new RuntimeException("GET 请求失败: " + url, e);} finally {try {httpClient.close();} catch (IOException e) {e.printStackTrace();}}}// -------------------- POST 表单请求 --------------------/*** 发送 POST 表单请求(application/x-www-form-urlencoded)* @param url       请求地址* @param params    表单参数(key-value)* @param ignoreSsl 是否忽略 SSL 证书校验(生产环境慎用)* @return 响应内容(字符串)*/public static String doPostForm(String url, Map<String, String> params, boolean ignoreSsl) {CloseableHttpClient httpClient = createHttpClient(ignoreSsl);HttpPost httpPost = new HttpPost(url);// 构建表单参数List<NameValuePair> formParams = new ArrayList<>();params.forEach((k, v) -> formParams.add(new BasicNameValuePair(k, v)));httpPost.setEntity(new UrlEncodedFormEntity(formParams, StandardCharsets.UTF_8));// 设置请求头(表单默认 Content-Type)httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded");try (CloseableHttpResponse response = httpClient.execute(httpPost)) {HttpEntity entity = response.getEntity();if (entity != null) {return EntityUtils.toString(entity, StandardCharsets.UTF_8);}return "";} catch (IOException e) {throw new RuntimeException("POST 表单请求失败: " + url, e);} finally {try {httpClient.close();} catch (IOException e) {e.printStackTrace();}}}// -------------------- POST JSON 请求 --------------------/*** 发送 POST JSON 请求(application/json)* @param url       请求地址* @param jsonBody  JSON 字符串* @param ignoreSsl 是否忽略 SSL 证书校验(生产环境慎用)* @return 响应内容(字符串)*/public static String doPostJson(String url, String jsonBody, boolean ignoreSsl) {CloseableHttpClient httpClient = createHttpClient(ignoreSsl);HttpPost httpPost = new HttpPost(url);// 设置请求头(JSON 场景)httpPost.setHeader("Content-Type", "application/json");httpPost.setEntity(new org.apache.http.entity.StringEntity(jsonBody, StandardCharsets.UTF_8));try (CloseableHttpResponse response = httpClient.execute(httpPost)) {HttpEntity entity = response.getEntity();if (entity != null) {return EntityUtils.toString(entity, StandardCharsets.UTF_8);}return "";} catch (IOException e) {throw new RuntimeException("POST JSON 请求失败: " + url, e);} finally {try {httpClient.close();} catch (IOException e) {e.printStackTrace();}}}// -------------------- 测试示例(main 方法) --------------------public static void main(String[] args) {// 1. GET 请求示例(带代理、忽略 SSL 校验)String getUrl = "https://www.example.com/api/get";String getResponse = doGet(getUrl, true);System.out.println("GET 响应: " + getResponse);}
}
  • HttpClientConfig.java
package com.test.demo.config;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;@Configuration
public class HttpClientConfig {@Beanpublic CloseableHttpClient httpClient() {// 这里可复用上面的 createHttpClient 逻辑,或直接构建带代理的 HttpClientreturn HttpProxyClientUtil.createHttpClient(true);}
}
  • ProxyHttpService.java
package com.test.demo.demos.web;import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.ParseException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.springframework.stereotype.Service;import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;@Service
public class ProxyHttpService {private final HttpClient httpClient;public ProxyHttpService(HttpClient httpClient) {this.httpClient = httpClient;}/*** 发送GET请求*/public String sendGetRequest(String url) throws IOException, ParseException {HttpGet httpGet = new HttpGet(url);try (CloseableHttpResponse response = (CloseableHttpResponse)httpClient.execute(httpGet)) {return EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);} catch (IOException e) {e.printStackTrace();throw new RuntimeException("请求失败", e);}}/*** 发送POST请求*/public String sendPostRequest(String url, Map<String, String> params) throws IOException, ParseException {HttpPost httpPost = new HttpPost(url);// 设置POST参数if (params != null && !params.isEmpty()) {List<NameValuePair> formParams = new ArrayList<>();for (Map.Entry<String, String> entry : params.entrySet()) {formParams.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));}httpPost.setEntity(new UrlEncodedFormEntity(formParams));}try (CloseableHttpResponse response = (CloseableHttpResponse) httpClient.execute(httpPost)) {HttpEntity entity = response.getEntity();return EntityUtils.toString(entity);}}
}
  • ProxyHttpController.java
package com.test.demo.demos.web;import org.springframework.web.bind.annotation.*;import java.io.IOException;
import java.util.HashMap;
import java.util.Map;@RestController
@RequestMapping("/proxy/api/http")
public class ProxyHttpController {private final ProxyHttpService proxyHttpService;public ProxyHttpController(ProxyHttpService proxyHttpService) {this.proxyHttpService = proxyHttpService;}/*** 通过代理发送GET请求*/@GetMapping("/get")public String sendGet() {try {return proxyHttpService.sendGetRequest("https://api.test.com.cn/sys/getCaptchaBase64");} catch (Exception e) {e.printStackTrace();return "Error: " + e.getMessage();}}/*** 通过代理发送POST请求*/@PostMapping("/post")public String sendPost(@RequestParam("url") String url,@RequestBody(required = false) Map<String, String> params) {try {return proxyHttpService.sendPostRequest(url, params);} catch (Exception e) {return "Error: " + e.getMessage();}}
}

3. SpringGateWay配置转发

方法2,对原项目代理改动还是比较大的,如果你使用的不是httpclient的请求方式,基于gateway批量转发,也是一个不错的选择。

  • 依赖
        <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-webflux</artifactId></dependency><dependency><groupId>io.projectreactor.netty</groupId><artifactId>reactor-netty-http</artifactId></dependency>
  • GatewayProxyConfig.java
package com.example.gateway.demos.web;import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.gateway.config.HttpClientCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import reactor.netty.http.client.HttpClient;
import reactor.netty.transport.ProxyProvider;import javax.net.ssl.SSLException;
import java.util.Arrays;@Configuration
public class GatewayProxyConfig {@Beanpublic HttpClientCustomizer proxyCustomizer(ProxyProperties proxyProperties) {return httpClient -> {// 使用最新的 ProxyProvider APIreturn httpClient.proxy(proxy -> {ProxyProvider.Builder builder = proxy.type(ProxyProvider.Proxy.HTTP).host(proxyProperties.getHost()).port(proxyProperties.getPort());// 如果需要代理认证if (proxyProperties.getUsername() != null) {builder.username(proxyProperties.getUsername()).password(s -> proxyProperties.getPassword());}//                    // 设置无需代理的主机列表
//                    if (proxyProperties.getNonProxyHosts() != null) {
//                        String[] nonProxyHosts = proxyProperties.getNonProxyHosts()
//                                .split(",");
//                        builder.nonProxyHosts(Arrays.toString(nonProxyHosts));
//                    }});};}@Beanpublic HttpClientCustomizer sslCustomizer() {return httpClient -> {// 创建信任所有证书的 SSLContext(测试环境)// 生产环境建议使用合法证书或自定义 TrustManagerreturn httpClient.secure(spec -> {try {spec.sslContext(buildInsecureSslContext());} catch (SSLException e) {e.printStackTrace();throw new RuntimeException(e);}});};}private io.netty.handler.ssl.SslContext buildInsecureSslContext() throws SSLException {return io.netty.handler.ssl.SslContextBuilder.forClient().trustManager(io.netty.handler.ssl.util.InsecureTrustManagerFactory.INSTANCE).build();}@Bean@ConfigurationProperties(prefix = "spring.cloud.gateway.httpclient.proxy")public ProxyProperties proxyProperties() {return new ProxyProperties();}// 代理配置属性类public static class ProxyProperties {private String host;private int port;private String username;private String password;private String nonProxyHosts;public String getHost() { return host; }public void setHost(String host) { this.host = host; }public int getPort() { return port; }public void setPort(int port) { this.port = port; }public String getUsername() { return username; }public void setUsername(String username) { this.username = username; }public String getPassword() { return password; }public void setPassword(String password) { this.password = password; }public String getNonProxyHosts() { return nonProxyHosts; }public void setNonProxyHosts(String nonProxyHosts) { this.nonProxyHosts = nonProxyHosts; }}
}
  • yml配置
# 应用服务 WEB 访问端口
server:port: 7777# application.yml
spring:cloud:gateway:httpclient:pool:max-connections: 500    # 最大连接数acquire-timeout: 45000  # 获取连接超时时间(毫秒)proxy:host: 10.10.10.61port: 8080# 如果需要认证# username: username# password: password# 非代理主机列表non-proxy-hosts: "localhost,127.0.0.1,*.local"routes:# 路由 ID,唯一标识- id: api2# 匹配的路径,所有以 /api/ 开头的请求都会被路由uri: https://api.api2.compredicates:- Path=/api2/**# 重写路径,去除 /api 前缀filters:- RewritePath=/api2/(?<segment>.*), /$\{segment}# 路由 ID,唯一标识- id: api1# 匹配的路径,所有以 /api/ 开头的请求都会被路由uri: https://api1.com.cnpredicates:- Path=/api1/**# 重写路径,去除 /api 前缀filters:- RewritePath=/api1/(?<segment>.*), /$\{segment}

4. Nginx配置转发

nginx配置这块,测试了很多方法,也没有非常有效的,最后放弃了

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/88145.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/88145.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python异步爬虫编程技巧:从入门到高级实战指南

Python异步爬虫编程技巧&#xff1a;从入门到高级实战指南 &#x1f680; &#x1f4da; 目录 前言&#xff1a;为什么要学异步爬虫异步编程基础概念异步爬虫核心技术栈入门实战&#xff1a;第一个异步爬虫进阶技巧&#xff1a;并发控制与资源管理高级实战&#xff1a;分布式…

JMeter-SSE响应数据自动化3.0

背景 此次因为多了一些需要过滤排除的错误(数量很少)&#xff0c;还需要修改下JMeter的jtl文件输出数据&#xff08;后续统计数据需要&#xff09; 所以只涉及到JSR脚本的一些改动(此部分改动并不会影响到JMeter的HTML报告) 改动 主要通过设置JMeter中prev输出数据变量threadN…

012 进程状态和优先级

&#x1f984; 个人主页: 小米里的大麦-CSDN博客 &#x1f38f; 所属专栏: Linux_小米里的大麦的博客-CSDN博客 &#x1f381; GitHub主页: 小米里的大麦的 GitHub ⚙️ 操作环境: Visual Studio 2022 文章目录 进程状态和优先级一、进程状态分类特殊状态说明 二、如何查看进程…

React JSX原理

JSX本质 实质上是React.createElement()的语法糖

Java-51 深入浅出 Tomcat 手写 Tomcat 类加载机制 双亲委派机制 生命周期 插件化

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; &#x1f680; AI篇持续更新中&#xff01;&#xff08;长期更新&#xff09; 目前2025年06月13日更新到&#xff1a; AI炼丹日志-28 - Aud…

从C++编程入手设计模式——责任链模式

从C编程入手设计模式——责任链模式 ​ 当我们的一个请求需要多个对象去处理&#xff0c;但具体由谁来处理&#xff0c;是根据情况动态决定的。例如&#xff0c;一个日志系统中&#xff0c;可能希望把错误信息写入文件&#xff0c;把提示信息输出到控制台&#xff0c;而不是每…

泛型方法调用需要显示指定泛型类型的场景

泛型类型的推断确定 一般来说&#xff0c;泛型类型的推断可以由以下几个场景确定&#xff1a; 变量定义指定类型 List<String> strList new ArrayList<>();ArrayList的泛型类型是依据变量的类型确定的。 方法返回值确定 Overridepublic Function<List<I…

Deep Research:开启深度研究的智能新时代

在当今信息爆炸的时代&#xff0c;人们面临着海量的信息&#xff0c;无论是专业人士还是普通消费者&#xff0c;都迫切需要一种高效、精准的方式来获取和分析信息。OpenAI 推出的 Deep Research&#xff0c;宛如一颗璀璨的新星&#xff0c;在知识的海洋中为我们导航&#xff0c…

曼昆《经济学原理》第九版 宏观经济学 第二十四章失业与自然失业率

以下是曼昆《经济学原理》第九版宏观经济学第二十四章**“失业与自然失业率”**的详细讲解&#xff0c;从零基础开始构建知识框架&#xff0c;结合中国实际案例与生活化比喻&#xff0c;帮助小白系统理解核心概念&#xff1a; 一、知识框架&#xff1a;失业的“全景图” 1. 核…

【软考高级系统架构论文】论软件系统架构风格

论文真题 请以“软件系统架构风格”为论题,依次从以下三个方面进行论述: 1、概要叙述你参与分析和开发的软件系统开发项目以及你所担任的主要工作。 2、分析软件系统开发中常用的软件系统架构风格有哪些?详细阐述每种风格的具体含义。 3、详细说明在你所参与的软件系统开发项…

LeetCode--35.搜索插入位置

解题思路&#xff1a; 1.获取信息&#xff1a; 给定一个升序排列的数组和一个整数&#xff0c;要求查找该整数应该在数组中插入的位置 限制条件是&#xff0c;要求时间复杂度为O(log N) 2.分析题目&#xff1a; 时间复杂度要求O(log N)&#xff0c;那么就使用二分查找法&#x…

Unix、Linux、POSIX、Minix 区别与联系

一、Unix&#xff1a;现代操作系统的技术原型 诞生&#xff1a;1969年贝尔实验室&#xff0c;用C语言重写后实现跨平台&#xff08;1973年&#xff09;。核心设计&#xff1a; 一切皆文件&#xff08;设备/进程均抽象为文件&#xff09;。管道&#xff08;|&#xff09;和文本…

python计算长方形的周长 2025年3月青少年电子学会等级考试 中小学生python编程等级考试一级真题答案解析

python计算长方形的周长 2025年3月 python编程等级考试一级编程题 博主推荐 所有考级比赛学习相关资料合集【推荐收藏】 1、Python比赛 信息素养大赛Python编程挑战赛 蓝桥杯python选拔赛真题详解 蓝桥杯python省赛真题详解 蓝桥杯python国赛真题详解 2、Python考级 p…

使用 RedisVL 进行复杂查询

一、前置条件 在开始之前&#xff0c;请确保&#xff1a; 已安装 redisvl 并激活相应的 Python 环境。运行 Redis 实例&#xff0c;且 RediSearch 版本 > 2.4。 二、初始化与数据加载 我们将使用一个包含用户信息的数据集&#xff0c;字段包括 user、age、job、credit_s…

「Linux文件及目录管理」vi、vim编辑器

知识点解析 vi/vim编辑器简介 vi:Linux默认的文本编辑器,基于命令行操作,功能强大。vim:vi的增强版,支持语法高亮、多窗口编辑、插件扩展等功能。vi/vim基本模式 命令模式:默认模式,用于移动光标、复制、粘贴、删除等操作。插入模式:按i进入,用于输入文本。末行模式:…

电容器保护测控装置如何选型?

在电力系统的无功补偿环节&#xff0c;​电容器保护测控装置是保障并联电容器组安全稳定运行的核心设备。其选型需综合考量保护需求、系统环境及扩展功能。以下是关键选型要素分析&#xff1a; ​一、明确核心功能需求​ 电容器保护测控装置&#xff0c;选型时需匹配电容器组实…

最近小峰一直在忙国际化项目,确实有点分身乏术... [特殊字符] 不过! 我正紧锣密鼓准备一系列干货文章/深度解析

本人详解 大家晚上好呀&#xff01;&#x1f319; 最近小峰一直在忙国际化项目&#xff0c;确实有点分身乏术... &#x1f605; 不过&#xff01; 我正紧锣密鼓准备一系列干货文章/深度解析&#xff08;选一个更符合你内容的词&#xff09;&#xff0c;很快就会和大家见面啦&am…

OpenCV CUDA模块设备层-----设备端(GPU)线程块级别的一个内存拷贝工具函数blockCopy()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 在同一个线程块&#xff08;thread block内&#xff0c;将 [beg, end) 范围内的数据并行地复制到 out 开始的位置。 它使用了 CUDA 线程协作机制…

https没有证书可以访问吗?外网怎么访问内网?

没有SSL证书的网站无法正常通过HTTPS协议访问‌。HTTPS的实现必须依赖有效的SSL证书完成加密握手&#xff0c;否则浏览器会直接阻断连接或显示严重的安全警告。‌‌ 一、技术实现层面‌ ‌HTTPS协议强制要求证书‌。 HTTPS基于SSL/TLS协议实现加密通信&#xff0c;而SSL证书是…

Python pytesseract【OCR引擎库】 简介

想全面了解DeepSeek的看过来 【包邮】DeepSeek全攻略 人人需要的AI通识课 零基础掌握DeepSeek的实用操作手册指南【限量作者亲笔签名版售完即止】 玩转DeepSeek这本就够了 【自营包邮】DeepSeek实战指南 deepseek从入门到精通实用操作指南现代科技科普读物AI普及知识读物人工智…