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. Redis 内存满了怎么办? Redis的内存淘汰策略

    https://juejin.im/post/5d674ac2e51d4557ca7fdd70 Redis占用内存大小 我们知道Redis是基于内存的key-value数据库,因为系统的内存大小有限, ...

  2. Symbol的isConcatSpreadable方法

    Symbol.isConcatSpreadable 布尔值,对象用于Array.prototype.concat()时,是否可以展开 let arr1 = ['c', 'd']; ['a', 'b'] ...

  3. 常见BUG

    1.没有配置Tomcat服务,由于 <exclusions> <exclusion> <groupId>org.springframework.boot</g ...

  4. python getattr函数的妙用

    import platform class Test: def test(self): func = getattr(self,'windows') func() @staticmethod def ...

  5. java: 列出本机java环境

    java: 列出本机java环境 System.getProperties().list(System.out);

  6. HTML中表格table标签的实例

    一.表格有边框,第一行居中对齐 二.表格没有边框 三.表格有水平标题 四.表格有垂直标题 五.合并行单元格 colspan合并单元格 六.表格有单元格边距(内边距) 七.表格没有单元格间距 八.表格有 ...

  7. cookie、session和会话保持

    1.会话 在程序中,会话跟踪是很重要的事情.理论上,一个已登录用户,在这次登录后进行的所有请求操作都应该属于同一个会话,而另一个用户的所有请求操作则应该属于另一个会话,二者不能混淆.例如,用户 A 在 ...

  8. apicloud直接上传图片

    function getPicture() { api.confirm({ title : "提示", msg : "选择图片", buttons : [&qu ...

  9. 多重背包的二进制优化——DP

    #include<cstdio> #include<cstring> #include<algorithm> #define LL long long using ...

  10. 3D Computer Grapihcs Using OpenGL - 03 OpenGL Buffer Data

    本节绘制一个三角形,并讲解Buffer Object-缓冲对象 OpenGL的窗口坐标 屏幕中心为坐标原点,横向朝右为x正方向,纵向朝上为y正方向,最大值最小值分别为1,-1. Buffer Obje ...