最近做接口开发,需要跟第三方系统对接接口,基于第三方系统接口的保密性,需要将调用方的请求IP加入到他们的白名单中。由于我们公司平常使用的公网的IP是不固定的,每次都需要将代码提交到固定的服务器上(服务器IP加入了第三方系统的白名单),频繁的修改提交合并代码和启动服务器造成了额外的工作量,给接口联调带来了很大的阻碍。
1、maven依赖
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
<version>4.4.10</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.6</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-io</artifactId>
<version>1.3.2</version>
</dependency>
2、正常的http请求
import org.apache.http.HttpEntity;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
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;
public static String getPost4Json(String url,String json)throws Exception{
CloseableHttpClient httpClient=HttpClients.createDefault();
HttpPost httpPost=new HttpPost(url);
/* 设置超时 */
RequestConfig defaultRequestConfig=RequestConfig.custom().setSocketTimeout(5000).setConnectTimeout(5000).setConnectionRequestTimeout(5000).build();
httpPost.setConfig(defaultRequestConfig);
httpPost.addHeader("Content-Type","application/json;charset=UTF-8");
httpPost.setEntity(new StringEntity(json,"UTF-8"));
CloseableHttpResponse response=null;
String result=null;
try{
response=httpClient.execute(httpPost);
HttpEntity entity = response.getEntity();
result=EntityUtils.toString(entity,"UTF-8");
}catch(Exception e){
throw e;
}finally{
if(response!=null) response.close();
httpClient.close();
}
return result;
}
由于没有加入白名单的原因,这样的请求显然无法调用到第三方的接口。这时候考虑能否将请求的ip改为白名单的一个ip,服务器在解析时拿到的不是正常的ip,这样能否正常调用呢?
3、伪造http请求ip地址
我们知道正常的tcp/ip在通信过程中是无法改变源ip的,也就是说电脑获取到的请求ip是不能改变的。但是可以通过伪造数据包的来源ip,即在http请求头加一个x-forwarded-for的头信息,这个头信息配置的是ip地址,它代表客户端,也就是HTTP的请求端真实的IP。因此在上面代码中加上如下代码:
httpPost.addHeader("x-forwarded-for",ip);
服务端通过x-forwarded-for获取请求ip,并且校验IP安全性,代码如下:
String ip = request.getHeader("x-forwarded-for");
4、总结
在请求头追加x-forwarded-for头信息可以伪造http请求ip地址。但是若服务器不直接信任并且不使用传递过来的 X-Forward-For 值的时候伪造IP就不生效了。