Apahce httpclient 提供HttpRequestInterceptor和HttpResponseInterceptor两种拦截器分别处理请求和响应数据,下面讲一下如何对http请求进行拦截并进行签名。

1、第一步创建拦截器对象实现HttpRequestInterceptor接口,并重写process方法

import org.apache.http.HttpException;
import org.apache.http.HttpRequest;
import org.apache.http.HttpRequestInterceptor;
import org.apache.http.protocol.HttpContext; import java.io.IOException; public class SpecialHttpRequestInterceptor implements HttpRequestInterceptor{
@Override
public void process(HttpRequest httpRequest, HttpContext httpContext) throws HttpException, IOException { }
}

2、获取签名需要的参数:path,method,url params,body,token

1> 首先拿到HttpRequest的封装类对象,HttpRequestWrapper: HttpRequestWrapper httpRequestWrapper = HttpRequestWrapper.class.cast(httpRequest);

PS:为什么转换成HttpRequestWrapper,是因为httpclient build生成InternalHttpClient(非异步)或InternalHttpAsyncClient(异步)对象时,InternalHttpClient或   InternalHttpAsyncClient对象的doExecute(非异步)或execute方法(异步)对HttpRequest对象进行封装,产生HttpRequestWrapper对象。拿到HttpRequestWrapper对象,大致的过程是这样的,具体可以去看一下httpclient的源码。

2>获取path:

  • 拿到HttpRequestWrapper对象后,获取URI:URI uri = httpRequestWrapper.getURI();
  • 获取Path:String path = uri.getPath();
  • 拿到URI后,生成URIBuilder:URIBuilder uriBuilder = new URIBuilder(uri),为什么要生成URIBuilder对象呢,是为了后面我们修改请求的参数

3>获取method:String method = httpRequestWrapper.getMethod();

4>获取HttpRequestWrapper内部封装的HttpRequest对象:HttpRequest originHttpRequest = httpRequestWrapper.getOriginal();

5>如果是post请求或者put请求,获取body(如果有的话)

String body = null;
HttpEntity entity = null;
if (originHttpRequest instanceof HttpPost) {
entity = ((HttpPost) originHttpRequest).getEntity();
} else if (originHttpRequest instanceof HttpPut) {
entity = ((HttpPut) originHttpRequest).getEntity();
}
if (entity != null) {
body = IOUtils.toString(entity.getContent(), CHARSET);
}

6>获取token(如果有的话)

String token = null;
Header header = originHttpRequest.getLastHeader("Authorization");
if(header != null && StringUtils.isNotEmpty(header.getValue())){
token = header.getValue();
}

7>最后就是用上面拿到的数据算签名并且加到parameters中,重新设置URI

下面是完整的代码:

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.*;
import org.apache.http.client.methods.*;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HttpContext;
import utils.SignUtil; import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLDecoder;
import java.util.*; public class SpecialHttpRequestInterceptor implements HttpRequestInterceptor {
private static final String CHARSET = "utf-8";
private static final String APP_ID = "10001";
private static final String SECRET_KEY = "123467"; @Override
public void process(HttpRequest httpRequest, HttpContext httpContext) throws IOException {
//获取HttpRequest的封装类,用于更改属性
HttpRequestWrapper httpRequestWrapper = HttpRequestWrapper.class.cast(httpRequest);
//获取请求方式
String method = httpRequestWrapper.getMethod();
//获取URIBuilder,用来重新设置parameters
URI uri = httpRequestWrapper.getURI();
URIBuilder uriBuilder = new URIBuilder(uri);
String path = uri.getPath();
//获取封装内部的原始HttpRequest对象
HttpRequest originHttpRequest = httpRequestWrapper.getOriginal();
String token = null;
String body = null;
//获取header中的token
Header header = originHttpRequest.getLastHeader("Authorization");
if (header != null && StringUtils.isNotEmpty(header.getValue())) {
token = header.getValue();
}
//如果是post或put请求,获取body HttpEntity entity = null;
if (originHttpRequest instanceof HttpPost) {
entity = ((HttpPost) originHttpRequest).getEntity();
} else if (originHttpRequest instanceof HttpPut) {
entity = ((HttpPut) originHttpRequest).getEntity();
}
if (entity != null) {
body = IOUtils.toString(entity.getContent(), CHARSET);
}
//生成签名并添加到paramters中
List<NameValuePair> pathParams = sign(path, method, uri, body, token);
uriBuilder.setParameters(pathParams);
try {
httpRequestWrapper.setURI(uriBuilder.build());
} catch (URISyntaxException e) {
e.printStackTrace();
}
} public List<NameValuePair> sign(String path, String method, URI uri, String body, String token) {
Map<String, String> urlMap = handleUri(uri);
List<NameValuePair> pathParams = addSign(path, method, urlMap, body, token);
return pathParams;
} public Map<String, String> handleUri(URI uri) {
Map<String, String> urlMap = new HashMap<>();
try {
String rawQuery = uri.getRawQuery();
if (StringUtils.isNotEmpty(rawQuery)) {
String queryParams = URLDecoder.decode(rawQuery, "utf-8");
String[] params = queryParams.split("&");
for (int i = 0; i < params.length; i++) {
String[] paramPair = params[i].split("=");
if (paramPair.length == 2) {
urlMap.put(String.valueOf(paramPair[0]), String.valueOf(paramPair[1]));
}
}
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return urlMap;
} public List<NameValuePair> addSign(String path, String method, Map<String, String> urlMap, String jsonBody, String token) {
List<NameValuePair> pathParams = new ArrayList<>();
String app_id = APP_ID;
String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
for (String key : urlMap.keySet()) {
if ("app_id".equals(key)) {
app_id = urlMap.get(key);
} else if ("timestamp".equals(key)) {
timestamp = urlMap.get(key);
} else {
pathParams.add(new BasicNameValuePair(key, urlMap.get(key)));
}
}
pathParams.add(new BasicNameValuePair("app_id", app_id));
pathParams.add(new BasicNameValuePair("timestamp", timestamp));
//真正算签名的地方
String sign = SignUtil.produceSign(path, method, token, pathParams, jsonBody, SECRET_KEY);
pathParams.add(new BasicNameValuePair("sign", sign));
return pathParams;
}
}

最新文章

  1. docker open files的设置
  2. Spring3博客(内含ppt和代码的github地址)
  3. CentOS搭建LNMP环境
  4. 30天轻松学习javaweb_模拟tomcat
  5. [Effective C++ --005]了解C++默默编写并调用哪些函数
  6. Ebean Demo
  7. Set Windows IP by Batch
  8. 实验六 多线程编程 1.随便选择两个城市作为预选旅游目标。实现两个独立的线程分别显示10次城市名,每次显示后休眠一段随机时间(1000ms以内),哪个先显示完毕,就决定去哪个城市。分别用Runnable接口和Thread类实现。
  9. Vue实现选项卡切换
  10. mongoDB常见的查询索引(三)
  11. Invalid bound statement (not found):xxx错误的可能原因
  12. oracle-logminer
  13. 微信H5开发
  14. JS中JSON.parse和eval的异同
  15. 【iCore1S 双核心板_ARM】例程十五:USB_HID实验——双向数据传输
  16. 【337】Text Mining Using Twitter Streaming API and Python
  17. 让子弹飞Demo版
  18. POJ 1436 Horizontally Visible Segments (线段树&amp;#183;区间染色)
  19. MATLAB基础知识tips
  20. 设计模式9---装饰模式(Decorator Pattern)

热门文章

  1. STM32F407 跑马灯实验
  2. Codeforces Round #427 (Div. 2) - D
  3. Ansbile实战经验
  4. Comet OJ - 模拟赛 #2 Day1 比赛总结
  5. java tomcat虚拟目录的深入了解
  6. java课堂测试2
  7. 【GDOI2014模拟】网格
  8. 【leetcode】1128. Number of Equivalent Domino Pairs
  9. 对postcss-plugin-px2rem的研究
  10. Go简易分布式对象存储 合并文件的所有分块为一个文件