Apache httpclient拦截器对请求进行签名
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拦截器对请求进行签名的更多相关文章
- 从一个舒服的姿势插入 HttpClient 拦截器技能点
马甲哥继续写一点大前端,阅读耗时5 minute,行文耗时5 Days 今天我们来了解一下如何拦截axios请求/响应? 这次我们举一反三,用一个最舒适的姿势插入这个技能点. axios是一个基于 p ...
- Java过滤器处理Ajax请求,Java拦截器处理Ajax请求,拦截器Ajax请求
Java过滤器处理Ajax请求,Java拦截器处理Ajax请求,拦截器Ajax请求 >>>>>>>>>>>>>>&g ...
- spring mvc 通过拦截器记录请求数据和响应数据
spring mvc 能过拦截器记录请求数据记录有很多种方式,主要有以下三种: 1:过滤器 2:HandlerInterceptor拦截器 3:Aspect接口控制器 但是就我个人所知要记录返回的数据 ...
- Angular4---认证---使用HttpClient拦截器,解决循环依赖引用的问题
在angular4 项目中,每次请求服务端需要添加头部信息AccessToken作为认证的凭据.但如果在每次调用服务端就要写代码添加一个头部信息,会变得很麻烦.可以使用angular4的HttpCli ...
- Structs2 中拦截器获取请求参数
前言 环境:window 10,JDK 1.7,Tomcat 7 测试代码 package com.szxy.interceptor; import java.util.Map; import jav ...
- vue 路由拦截器和请求拦截器
路由拦截器 已路由为导向 router.beforeEach((to,from,next)=>{ if(to.path=='/login' || localStorage.getItem('to ...
- 五、Vue:使用axios库进行get和post、用拦截器对请求和响应进行预处理、Mock(数据模拟)
一.axios [应用]进行请求和传表单 [axios中文档]:https://www.kancloud.cn/yunye/axios/234845 [vue-axios]:https://cn.vu ...
- vue+axois 封装请求+拦截器(请求锁+统一错误)
需求 封装常用请求 拦截器-请求锁 统一处理错误码 一.封装常用的请求 解决痛点:不要每一个模块的api都还要写get,post,patch请求方法.直接将这些常用的方法封装好. 解决方案:写一个类 ...
- springweb项目自定义拦截器修改请求报文头
面向切面,法力无边,任何脏活累活,都可以从干干净净整齐划一的业务代码中抽出来,无非就是加一层,项目里两个步骤间可以被分层的设计渗透成筛子. 举个例子: 最近我们对接某银行接口,我们的web服务都是标准 ...
随机推荐
- 04javascript03
DOM简介 1.获得元素 <!DOCTYPE html> <html> <head> <title>MyHtml.html</title> ...
- python数组中在某一元素前插入数据
# 已知有一个已经排好序的数组.要求是,有一个新数据项,要求按原来的规律将它插入数组中. a=[1,2,3,4,5,6,7,8,9]num=int(input("input num:&quo ...
- Python---面向对象---案例
a = 5print(5/10)# 地板除(功能类似于数学模块当中floor()向下取整操作)print(5//10)print(a%10)b = 25print(b/10)print(b//10)p ...
- 【NOIP2016提高组A组7.16】大鱼海棠
题目 椿是掌管海棠花的少女,她所在的世界不为人们所知,他们的天空就是人类的海底.生活在那个世界里的他们不是人,也不是鱼,而是其他人,掌管着人间的规律. 按照他们的习俗,在16岁那年,椿变为一条海豚到人 ...
- 【GDOI2016模拟3.10】习用之语
前言 这道题看上去很水,结果我在比赛上浪费了N多时间在上面,但还是没AC.比赛结束后发现:实际上这道题还是是大水. 题目 分析 设字符串c1c2c3c4,其中c1.c2.c3.c4={'0'~'9', ...
- Serverless Kubernetes入门:对kubernetes做减法
背景 Kubernetes作为通用的容器编排系统,承载了广泛的应用和场景,包括CI/CD,数据计算,在线应用,AI等,然而由于其通用性和复杂性,管理一个kubernetes集群对于很多用户而言还是充满 ...
- 自动配置/切换/查看JDK环境变量
最近老是需要几个版本的JDK切换工作,于是网上收集资料整理,自己写了一个:自动配置/切换/查看JDK环境变量的批处理脚本.顺带3个JDK版本分别是:jdk1.6.0_43,jdk1.7.0_80,jd ...
- php array_push()函数 语法
php array_push()函数 语法 作用:向第一个参数的数组尾部添加一个或多个元素(入栈),然后返回新数组的长度.博智达 语法:array_push(array,value1,value2.. ...
- Mysql数据库常见试题
引用自http://blog.csdn.net/laoniyouxi123/article/details/51161157 sql语句应该考虑哪些安全性? 答: (1)防止sql注入,对特殊字符进行 ...
- HDU 1298 T9 ( 字典树 )
题意 : 给你 w 个单词以及他们的频率,现在给出模拟 9 键打字的一串数字,要你在其模拟打字的过程中给出不同长度的提示词,出现的提示词应当是之前频率最高的,当然提示词不需要完整的,也可以是 w 个单 ...