Apahce httpclient 提供HttpRequestInterceptor和
HttpResponseInterceptor兩種攔截器分別處理請求和響應數據,下面講一下如何對http請求進行攔截並進行簽名。java
一、第一步建立攔截器對象實現HttpRequestInterceptor接口,並重寫process方法apache
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 { } }
二、獲取簽名須要的參數:path,method,url params,body,tokenjson
1> 首先拿到HttpRequest的封裝類對象,HttpRequestWrapper: HttpRequestWrapper httpRequestWrapper = HttpRequestWrapper.class.cast(httpRequest); app
PS:爲何轉換成HttpRequestWrapper,是由於httpclient build生成InternalHttpClient(非異步)或InternalHttpAsyncClient(異步)對象時,InternalHttpClient或 InternalHttpAsyncClient對象的doExecute(非異步)或execute方法(異步)對HttpRequest對象進行封裝,產生HttpRequestWrapper對象。拿到HttpRequestWrapper對象,大體的過程是這樣的,具體能夠去看一下httpclient的源碼。 異步
2>獲取path:ide
3>獲取method:String method = httpRequestWrapper.getMethod();post
4>獲取HttpRequestWrapper內部封裝的HttpRequest對象:HttpRequest originHttpRequest = httpRequestWrapper.getOriginal();ui
5>若是是post請求或者put請求,獲取body(若是有的話)url
String body = null; if(originHttpRequest instanceof HttpPost || originHttpRequest instanceof HttpPut){ HttpEntity entity = ((HttpPost)originHttpRequest).getEntity(); if(entity != null){ body = IOUtils.toString(entity.getContent(), CHARSET); } }
6>獲取token(若是有的話)spa
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 if (originHttpRequest instanceof HttpPost || originHttpRequest instanceof HttpPut) { HttpEntity entity = ((HttpPost) 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; } }