使用RestTemplate模拟Postman请求失败,求解决方案
我尝试从https://ws-public.interpol.int/notices/v1/red获取JSON数据,该请求在Postman中可正常运行:

但当我使用Spring的RestTemplate按如下代码(尝试完全复制请求头)模拟时:
final HttpHeaders headers = new HttpHeaders(); headers.set(HttpHeaders.CACHE_CONTROL, "no-cache"); headers.set(HttpHeaders.USER_AGENT, "PostmanRuntime/7.42.0"); headers.set(HttpHeaders.HOST, "ws-public.interpol.int"); headers.set(HttpHeaders.ACCEPT, "*/*"); headers.set(HttpHeaders.ACCEPT_ENCODING, "gzip, deflate, br"); headers.set(HttpHeaders.CONNECTION, "keep-alive"); final HttpEntity<Void> entity = new HttpEntity<>((Void) null, headers); final RestTemplate restTemplate = new RestTemplateBuilder() .setConnectTimeout(Duration.ofMillis(5000L)) .setReadTimeout(Duration.ofMillis(5000L)) .build(); final String response = restTemplate .exchange(URL, HttpMethod.GET, entity, String.class) .getBody();
请求失败并返回403 Forbidden:
Exception in thread "main" org.springframework.web.client.HttpClientErrorException$Forbidden: 403 Forbidden: "<HTML><HEAD><LF><TITLE>Access Denied</TITLE><LF></HEAD><BODY><LF><H1>Access Denied</H1><LF> <LF>You don't have permission to access "http://ws-public.interpol.int/" on this server.<P><LF>Reference #18.1cf95568.1730991641.2abc645d<LF><P>https://errors.edgesuite.net/18.1cf95568.1730991641.2abc645d</P><LF></BODY><LF></HTML><LF>" at org.springframework.web.client.HttpClientErrorException.create(HttpClientErrorException.java:109) at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:168) at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:122) at org.springframework.web.client.ResponseErrorHandler.handleError(ResponseErrorHandler.java:63) at org.springframework.web.client.RestTemplate.handleResponse(RestTemplate.java:819) at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:777) at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:711) at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:602) at com.company.sample.MySampleApp.main(MySampleApp.java:55)
请问如何成功模拟Postman的请求?我遗漏了哪些配置?
出现403 Forbidden通常是因为RestTemplate的请求与Postman的请求存在细节差异,服务器的验证或反爬机制拒绝了请求,可按以下步骤修复:
1. 移除手动设置的HOST头
RestTemplate会自动根据请求URL生成正确的HOST头,手动设置可能导致格式或值的不一致,直接删除headers.set(HttpHeaders.HOST, "ws-public.interpol.int");这行代码。
2. 完整复制Postman的所有请求头
Postman会自动添加一些隐藏的请求头,你需要把这些头也加入到RestTemplate的HttpHeaders中:
- 在Postman的请求页面,点击Headers选项卡,勾选"Show auto-generated headers",查看所有发送的头信息
- 将所有头(比如
Accept-Language、DNT、Postman-Token等)逐一添加到代码的HttpHeaders里
3. 更换请求工厂为Apache HttpClient
RestTemplate默认使用的SimpleClientHttpRequestFactory兼容性有限,换成Apache HttpClient可以更好地模拟Postman的请求行为:
首先引入Maven依赖:
<dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.14</version> </dependency>
然后修改RestTemplate的构建代码:
import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder; import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; // ... CloseableHttpClient httpClient = HttpClientBuilder.create() .build(); ClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(httpClient); RestTemplate restTemplate = new RestTemplateBuilder() .setConnectTimeout(Duration.ofMillis(5000L)) .setReadTimeout(Duration.ofMillis(5000L)) .requestFactory(() -> requestFactory) .build();
4. 检查并添加Cookie(如果需要)
Postman会自动保存服务器返回的Cookie,后续请求会自动携带。你可以在Postman的Response Headers中查看Set-Cookie字段,然后在RestTemplate中手动添加Cookie头:
headers.add("Cookie", "替换为Postman中获取到的Cookie内容");
完成以上步骤后,重新发起请求,即可和Postman一样正常获取数据。
内容的提问来源于stack exchange,提问作者Hasan Can Saral

