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;
}
}

Apache httpclient拦截器对请求进行签名的更多相关文章

  1. 从一个舒服的姿势插入 HttpClient 拦截器技能点

    马甲哥继续写一点大前端,阅读耗时5 minute,行文耗时5 Days 今天我们来了解一下如何拦截axios请求/响应? 这次我们举一反三,用一个最舒适的姿势插入这个技能点. axios是一个基于 p ...

  2. Java过滤器处理Ajax请求,Java拦截器处理Ajax请求,拦截器Ajax请求

    Java过滤器处理Ajax请求,Java拦截器处理Ajax请求,拦截器Ajax请求 >>>>>>>>>>>>>>&g ...

  3. spring mvc 通过拦截器记录请求数据和响应数据

    spring mvc 能过拦截器记录请求数据记录有很多种方式,主要有以下三种: 1:过滤器 2:HandlerInterceptor拦截器 3:Aspect接口控制器 但是就我个人所知要记录返回的数据 ...

  4. Angular4---认证---使用HttpClient拦截器,解决循环依赖引用的问题

    在angular4 项目中,每次请求服务端需要添加头部信息AccessToken作为认证的凭据.但如果在每次调用服务端就要写代码添加一个头部信息,会变得很麻烦.可以使用angular4的HttpCli ...

  5. Structs2 中拦截器获取请求参数

    前言 环境:window 10,JDK 1.7,Tomcat 7 测试代码 package com.szxy.interceptor; import java.util.Map; import jav ...

  6. vue 路由拦截器和请求拦截器

    路由拦截器 已路由为导向 router.beforeEach((to,from,next)=>{ if(to.path=='/login' || localStorage.getItem('to ...

  7. 五、Vue:使用axios库进行get和post、用拦截器对请求和响应进行预处理、Mock(数据模拟)

    一.axios [应用]进行请求和传表单 [axios中文档]:https://www.kancloud.cn/yunye/axios/234845 [vue-axios]:https://cn.vu ...

  8. vue+axois 封装请求+拦截器(请求锁+统一错误)

     需求 封装常用请求 拦截器-请求锁 统一处理错误码 一.封装常用的请求 解决痛点:不要每一个模块的api都还要写get,post,patch请求方法.直接将这些常用的方法封装好. 解决方案:写一个类 ...

  9. springweb项目自定义拦截器修改请求报文头

    面向切面,法力无边,任何脏活累活,都可以从干干净净整齐划一的业务代码中抽出来,无非就是加一层,项目里两个步骤间可以被分层的设计渗透成筛子. 举个例子: 最近我们对接某银行接口,我们的web服务都是标准 ...

随机推荐

  1. linux系统下如何在vscode中调试C++代码

    本篇博客以一个简单的hello world程序,介绍在vscode中调试C++代码的配置过程. 1. 安装编译器 vscode是一个轻量的代码编辑器,并不具备代码编译功能,代码编译需要交给编译器完成. ...

  2. PAT Advanced 1019 General Palindromic Number (20 分)

    A number that will be the same when it is written forwards or backwards is known as a Palindromic Nu ...

  3. ZX树初步

    一些数据结构,比如线段树或平衡树,他们一般是要么维护每个元素在原序列中的排列顺序,要么是维护每个元素的大小顺序,若是像二者兼得那么就想想主席树. 给你多个不同的数字问你1-N第K大的数是多少 最简单的 ...

  4. python文件读写详解

    # Python3 open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, ...

  5. java:Conllection中的List,ArrayList添加元素,删除元素,输出元素

    java:Conllection中的List,ArrayList添加元素,删除元素,输出元素 //为list接口实例化 List<String> addlist = new ArrayLi ...

  6. zabbix监控A主机到B主机的网络质量

    采用zabbix自带的icmp ping即可进行监控: 1.安装fping 2.将fping安装后链接到/usr/sbin/fping下,设置组为zabbix; 3.增加监控项:icmpping[ip ...

  7. 在mac上安装rabbitmq

    在 OS X 上安装 RabbitMQ¶ 在 Snow Leopard 上安装 RabbitMQ 最简单的方式就是 Homebrew ——OS X 上的一款新颖别致,光彩动人的包管理系统. 在本例中, ...

  8. android 开发架构学习

    Android DataBinding(数据绑定)入门与实战 http://examplecode.cn/2018/07/20/android-databinding-01-introduction/ ...

  9. Bugku web web2

    web2 打开后发现是个大滑稽啊!F12检查元素拿到flag

  10. 配置服务器(anaconda + jupyter + R)

    总结一下整体的流程: 1. 服务器安装anaconda 首先清华镜像站下载anaconda3. 2. 将下载好的文件用scp命令传入服务器 注意:指定端口用-P命令 p大写 本机地址 用户名@服务器I ...