Apache httpclient攔截器對請求進行簽名

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

 

  • 拿到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();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;
    }
}
相關文章
相關標籤/搜索