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;
    }
}

 

posted @ 2019-10-15 19:08  弘文馆校书  阅读(3865)  评论(0编辑  收藏  举报