Apachehttpclient拦截器对请求进行签名

编程

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;

}

}

以上是 Apachehttpclient拦截器对请求进行签名 的全部内容, 来源链接: utcz.com/z/511799.html

回到顶部