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. Peakvue和自相关技术轴承诊断

    什么是应力波 应力波产生于“金属与金属相互碰撞的事件” 加速度传感器捕捉含有具有短时特性应力波的轴承振动信号 应力波是一种非常短暂的连续的脉冲信号, 通常在百万分之一秒到千分之一秒的区间范围内, 它是 ...

  2. tf中的meta和pb

    https://www.jianshu.com/p/af2b694eae61 简单来说,pb文件是个推理的图,meta更复杂,不能用来部署

  3. java.sql.SQLException: Unknown system variable 'query_cache_size'

    改为 <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java< ...

  4. cocos随笔

    随笔:  [ 1 ] active能隐藏元素,且不占空间,但仍存在,索引时,仍能得到 [ 2 ] 碰到参数传不进去的时候可以试着用属性赋值的方法代替传参 [ 3 ] getChildByName是按照 ...

  5. 前端之JavaScript:JS之DOM对象二

    继续JS之DOM对象二 前面在JS之DOM中我们知道了属性操作,下面我们来了解一下节点操作.很重要!! 一.节点操作 创建节点:var ele_a = document.createElement(' ...

  6. 关于下拉框的onchange事件和onclick选择value值。

    下拉框的onchange事件和onclick,一般最好都选择onchange事件,onclick可能会不兼容有些浏览器. 下面是代码: <!DOCTYPE html><html la ...

  7. 《SaltStack技术入门与实践》—— Event和Reactor系统

    Event和Reactor系统 本章节参考<SaltStack技术入门与实践>,感谢该书作者: 刘继伟.沈灿.赵舜东 Event是SaltStack里面的对每个事件的一个记录,它相比job ...

  8. clang和llvm的安装

    https://blog.csdn.net/qq_31157999/article/details/78906982

  9. 51Nod 1277 字符串中的最大值 ( KMP && DP )

    题意 : 一个字符串的前缀是指包含该字符第一个字母的连续子串,例如:abcd的所有前缀为a, ab, abc, abcd.给出一个字符串S,求其所有前缀中,字符长度与出现次数的乘积的最大值.例如:S ...

  10. 安装k8s集群(亲测)

    先安装一台虚拟机,然后进行克隆,因为前面的步骤都是一样的,具体代码如下: Last login: Mon Nov 25 00:40:34 2019 from 192.168.180.1 ##安装依赖包 ...