• 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;
        }
    }
  • 相关阅读:
    WPF系列四
    (最近新弄的几个小demo) 之 (模仿百度搜索框)后续更新中,比较实用
    WPF系列二
    使用IHttpAsyncHandler实现服务器推送技术
    JS中的substring和substr函数的区别
    JS图片自动切换
    Builder生成器模式
    Adapter适配器模式
    Singleton单例模式
    Prototype原型模式
  • 原文地址:https://www.cnblogs.com/Eric-zhao/p/11679643.html
Copyright © 2020-2023  润新知