/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.xmomen.module.sms.util; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.net.MalformedURLException; import java.net.URLEncoder; import java.nio.ByteBuffer; import java.nio.channels.Channels; import java.nio.channels.ReadableByteChannel; import java.nio.channels.WritableByteChannel; import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import org.apache.commons.lang.StringUtils; import org.apache.http.Header; import org.apache.http.HttpResponse; import org.apache.http.NameValuePair; import org.apache.http.client.HttpClient; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.HttpDelete; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpPut; import org.apache.http.conn.ClientConnectionManager; import org.apache.http.conn.scheme.Scheme; import org.apache.http.conn.scheme.SchemeRegistry; import org.apache.http.conn.ssl.SSLSocketFactory; import org.apache.http.entity.ByteArrayEntity; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.message.BasicNameValuePair; import org.apache.http.params.CoreConnectionPNames; import com.xmomen.module.sms.api.Response; import com.xmomen.module.sms.constant.Constants; import com.xmomen.module.sms.constant.ContentType; import com.xmomen.module.sms.constant.HttpHeader; import com.xmomen.module.sms.constant.HttpMethod; import com.xmomen.module.sms.constant.SystemHeader; /** * Http工具类 */ public class HttpUtil { /** * HTTP GET * @param host * @param path * @param connectTimeout * @param headers * @param querys * @param signHeaderPrefixList * @param appKey * @param appSecret * @return * @throws Exception */ public static Response httpGet(String host, String path, int connectTimeout, Map headers, Map querys, List signHeaderPrefixList, String appKey, String appSecret) throws Exception { // 初始化基础Header // 初始化基础Header headers = initialBasicHeader(HttpMethod.GET, path, headers, querys, null, signHeaderPrefixList, appKey, appSecret); // 创建HttpClient对象 // 设置连接超时时间 // 创建HttpClient对象 HttpClient httpClient = wrapClient(host); // 创建HttpGet对象 // 设置连接超时时间 httpClient.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, getTimeout(connectTimeout)); // 添加Header // 创建HttpGet对象 HttpGet get = new HttpGet(initUrl(host, path, querys)); // 执行请求并返回Response // 添加Header for (Map.Entry e : headers.entrySet()) { get.addHeader(e.getKey(), MessageDigestUtil.utf8ToIso88591(e.getValue())); } // 执行请求并返回Response return convert(httpClient.execute(get)); } /** * HTTP POST表单 * @param host * @param path * @param connectTimeout * @param headers * @param querys * @param bodys * @param signHeaderPrefixList * @param appKey * @param appSecret * @return * @throws Exception */ // 设置Content-Type为表单类型 public static Response httpPost(String host, String path, int connectTimeout, Map headers, Map querys, Map bodys, List signHeaderPrefixList, String appKey, String appSecret) throws Exception { // 初始化基础Header if (headers == null) { headers = new HashMap(); // 创建HttpClient对象 } // 设置连接超时时间 // 设置Content-Type为表单类型 // 创建HttpPost对象 headers.put(HttpHeader.HTTP_HEADER_CONTENT_TYPE, ContentType.CONTENT_TYPE_FORM); // 添加Header // 初始化基础Header headers = initialBasicHeader(HttpMethod.POST, path, headers, querys, bodys, signHeaderPrefixList, appKey, appSecret); // 构建表单实体 // 创建HttpClient对象 HttpClient httpClient = wrapClient(host); // 设置连接超时时间 httpClient.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, getTimeout(connectTimeout)); // 执行请求并返回Response // 创建HttpPost对象 HttpPost post = new HttpPost(initUrl(host, path, querys)); // 添加Header for (Map.Entry e : headers.entrySet()) { post.addHeader(e.getKey(), MessageDigestUtil.utf8ToIso88591(e.getValue())); } // 构建表单实体 UrlEncodedFormEntity formEntity = buildFormEntity(bodys); if (formEntity != null) { post.setEntity(formEntity); } // 执行请求并返回Response return convert(httpClient.execute(post)); } /** * Http POST 字符串 // 初始化基础Header * @param host * @param path // 创建HttpClient对象 * @param connectTimeout // 设置连接超时时间 * @param headers * @param querys // 创建HttpPost对象 * @param body // 添加Header * @param signHeaderPrefixList * @param appKey // 初始化基础Header * @param appSecret // 设置请求体 * @return // 创建HttpClient对象 * @throws Exception // 设置连接超时时间 */ // 执行请求并返回Response public static Response httpPost(String host, String path, int connectTimeout, Map headers, Map querys, String body, List signHeaderPrefixList, String appKey, String appSecret) // 创建HttpPost对象 throws Exception { // 添加Header headers = initialBasicHeader(HttpMethod.POST, path, headers, querys, null, signHeaderPrefixList, appKey, appSecret); HttpClient httpClient = wrapClient(host); httpClient.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, getTimeout(connectTimeout)); // 设置请求体 HttpPost post = new HttpPost(initUrl(host, path, querys)); for (Map.Entry e : headers.entrySet()) { post.addHeader(e.getKey(), MessageDigestUtil.utf8ToIso88591(e.getValue())); // 执行请求并返回Response } if (StringUtils.isNotBlank(body)) { post.setEntity(new StringEntity(body, Constants.ENCODING)); // 初始化基础Header } // 创建HttpClient对象 return convert(httpClient.execute(post)); // 设置连接超时时间 } // 创建HttpPost对象 /** // 添加Header * HTTP POST 字节数组 // 初始化基础Header * @param host * @param path // 设置请求体 // 创建HttpClient对象 * @param connectTimeout // 设置连接超时时间 * @param headers // 执行请求并返回Response * @param querys // 创建HttpPost对象 * @param bodys // 添加Header * @param signHeaderPrefixList * @param appKey * @param appSecret * @return // 设置请求体 * @throws Exception */ // 执行请求并返回Response public static Response httpPost(String host, String path, int connectTimeout, Map headers, Map querys, byte[] bodys, List signHeaderPrefixList, String appKey, String appSecret) throws Exception { headers = initialBasicHeader(HttpMethod.POST, path, headers, querys, null, signHeaderPrefixList, appKey, appSecret); HttpClient httpClient = wrapClient(host); httpClient.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, getTimeout(connectTimeout)); // 初始化基础Header HttpPost post = new HttpPost(initUrl(host, path, querys)); for (Map.Entry e : headers.entrySet()) { // 创建HttpClient对象 post.addHeader(e.getKey(), MessageDigestUtil.utf8ToIso88591(e.getValue())); // 设置连接超时时间 } // 创建HttpPut对象 if (bodys != null) { // 添加Header post.setEntity(new ByteArrayEntity(bodys)); // 初始化基础Header } // 设置请求体 // 创建HttpClient对象 return convert(httpClient.execute(post)); // 设置连接超时时间 } // 执行请求并返回Response // 创建HttpPut对象 /** // 添加Header * HTTP PUT 字符串 * @param host * @param path * @param connectTimeout // 设置请求体 * @param headers * @param querys * @param body // 执行请求并返回Response * @param signHeaderPrefixList * @param appKey * @param appSecret * @return * @throws Exception */ public static Response httpPut(String host, String path, int connectTimeout, Map headers, Map querys, String body, List signHeaderPrefixList, String appKey, String appSecret) // 初始化基础Header throws Exception { headers = initialBasicHeader(HttpMethod.PUT, path, headers, querys, null, signHeaderPrefixList, appKey, appSecret); // 创建HttpClient对象 // 设置连接超时时间 HttpClient httpClient = wrapClient(host); httpClient.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, getTimeout(connectTimeout)); // 创建HttpPut对象 // 添加Header HttpPut put = new HttpPut(initUrl(host, path, querys)); // 初始化基础Header for (Map.Entry e : headers.entrySet()) { put.addHeader(e.getKey(), MessageDigestUtil.utf8ToIso88591(e.getValue())); // 设置请求体 // 创建HttpClient对象 } // 设置连接超时时间 // 执行请求并返回Response if (StringUtils.isNotBlank(body)) { // 创建HttpPut对象 put.setEntity(new StringEntity(body, Constants.ENCODING)); // 添加Header } // 设置请求体 return convert(httpClient.execute(put)); } // 执行请求并返回Response /** * HTTP PUT字节数组 * @param host * @param path * @param connectTimeout * @param headers // 初始化基础Header * @param querys * @param bodys // 创建HttpClient对象 * @param signHeaderPrefixList // 设置连接超时时间 * @param appKey * @param appSecret // 创建HttpDelete对象 * @return // 添加Header * @throws Exception // 初始化基础Header */ public static Response httpPut(String host, String path, int connectTimeout, Map headers, Map querys, byte[] bodys, List signHeaderPrefixList, String appKey, String appSecret) // 执行请求并返回Response // 创建HttpClient对象 throws Exception { // 设置连接超时时间 headers = initialBasicHeader(HttpMethod.PUT, path, headers, querys, null, signHeaderPrefixList, appKey, appSecret); // 创建HttpDelete对象 HttpClient httpClient = wrapClient(host); // 添加Header httpClient.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, getTimeout(connectTimeout)); HttpPut put = new HttpPut(initUrl(host, path, querys)); // 执行请求并返回Response for (Map.Entry e : headers.entrySet()) { put.addHeader(e.getKey(), MessageDigestUtil.utf8ToIso88591(e.getValue())); } // 构建表单参数 if (bodys != null) { put.setEntity(new ByteArrayEntity(bodys)); } return convert(httpClient.execute(put)); } // 构建表单参数 /** * HTTP DELETE * @param host * @param path * @param connectTimeout * @param headers * @param querys * @param signHeaderPrefixList * @param appKey * @param appSecret * @return * @throws Exception */ public static Response httpDelete(String host, String path, int connectTimeout, Map headers, Map querys, List signHeaderPrefixList, String appKey, String appSecret) throws Exception { headers = initialBasicHeader(HttpMethod.DELETE, path, headers, querys, null, signHeaderPrefixList, appKey, appSecret); HttpClient httpClient = wrapClient(host); httpClient.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, getTimeout(connectTimeout)); HttpDelete delete = new HttpDelete(initUrl(host, path, querys)); for (Map.Entry e : headers.entrySet()) { delete.addHeader(e.getKey(), MessageDigestUtil.utf8ToIso88591(e.getValue())); } return convert(httpClient.execute(delete)); } /** * 构建FormEntity * * @param formParam * @return * @throws UnsupportedEncodingException */ private static UrlEncodedFormEntity buildFormEntity(Map formParam) throws UnsupportedEncodingException { if (formParam != null) { List nameValuePairList = new ArrayList(); for (String key : formParam.keySet()) { nameValuePairList.add(new BasicNameValuePair(key, formParam.get(key))); } UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(nameValuePairList, Constants.ENCODING); formEntity.setContentType(ContentType.CONTENT_TYPE_FORM); return formEntity; } return null; } private static String initUrl(String host, String path, Map querys) throws UnsupportedEncodingException { StringBuilder sbUrl = new StringBuilder(); sbUrl.append(host); if (!StringUtils.isBlank(path)) { sbUrl.append(path); } if (null != querys) { // 添加时间戳 // 添加时间戳 // 添加随机数 StringBuilder sbQuery = new StringBuilder(); // 添加AppKey // 添加随机数 // 添加签名 for (Map.Entry query : querys.entrySet()) { // 添加AppKey if (0 < sbQuery.length()) { // 添加签名 sbQuery.append(Constants.SPE3); } if (StringUtils.isBlank(query.getKey()) && !StringUtils.isBlank(query.getValue())) { sbQuery.append(query.getValue()); } if (!StringUtils.isBlank(query.getKey())) { sbQuery.append(query.getKey()); if (!StringUtils.isBlank(query.getValue())) { sbQuery.append(Constants.SPE4); sbQuery.append(URLEncoder.encode(query.getValue(), Constants.ENCODING)); } } } if (0 < sbQuery.length()) { sbUrl.append(Constants.SPE5).append(sbQuery); } } return sbUrl.toString(); } // 设置状态码 // 设置Header /** * 初始化基础Header // 设置状态码 // 设置Content-Type * @param method // 设置RequestId // 设置Header // 设置ErrorMessage * @param path // 设置Body * @param headers * @param querys * @param bodys // 设置Content-Type * @param signHeaderPrefixList // 设置RequestId * @param appKey // 设置ErrorMessage * @param appSecret // 设置Body * @return * @throws MalformedURLException */ private static Map initialBasicHeader(String method, String path, Map headers, Map querys, Map bodys, List signHeaderPrefixList, String appKey, String appSecret) throws MalformedURLException { if (headers == null) { headers = new HashMap(); } headers.put(SystemHeader.X_CA_TIMESTAMP, String.valueOf(new Date().getTime())); // 读取流并转换为字符串 //headers.put(SystemHeader.X_CA_NONCE, UUID.randomUUID().toString()); headers.put(SystemHeader.X_CA_KEY, appKey); headers.put(SystemHeader.X_CA_SIGNATURE, SignUtil.sign(appSecret, method, path, headers, querys, bodys, signHeaderPrefixList)); return headers; } // 读取流并转换为字符串 /** * 读取超时时间 * * @param timeout * @return */ private static int getTimeout(int timeout) { if (timeout == 0) { return Constants.DEFAULT_TIMEOUT; } return timeout; } // 创建SSLContext对象 // 创建X509TrustManager对象 private static Response convert(HttpResponse response) throws IOException { Response res = new Response(); if (null != response) { res.setStatusCode(response.getStatusLine().getStatusCode()); for (Header header : response.getAllHeaders()) { // 创建SSLContext对象 res.setHeader(header.getName(), MessageDigestUtil.iso88591ToUtf8(header.getValue())); // 创建X509TrustManager对象 } res.setContentType(res.getHeader("Content-Type")); res.setRequestId(res.getHeader("X-Ca-Request-Id")); res.setErrorMessage(res.getHeader("X-Ca-Error-Message")); res.setBody(readStreamAsStr(response.getEntity().getContent())); } else { //服务器无回应 res.setStatusCode(500); res.setErrorMessage("No Response"); } return res; } /** * 将流转换为字符串 * * @param is * @return * @throws IOException */ public static String readStreamAsStr(InputStream is) throws IOException { ByteArrayOutputStream bos = new ByteArrayOutputStream(); WritableByteChannel dest = Channels.newChannel(bos); ReadableByteChannel src = Channels.newChannel(is); ByteBuffer bb = ByteBuffer.allocate(4096); while (src.read(bb) != -1) { bb.flip(); dest.write(bb); bb.clear(); } src.close(); dest.close(); return new String(bos.toByteArray(), Constants.ENCODING); } private static HttpClient wrapClient(String host) { HttpClient httpClient = new DefaultHttpClient(); if (host.startsWith("https://")) { sslClient(httpClient); } return httpClient; } private static void sslClient(HttpClient httpClient) { try { SSLContext ctx = SSLContext.getInstance("TLS"); X509TrustManager tm = new X509TrustManager() { public X509Certificate[] getAcceptedIssuers() { return null; } public void checkClientTrusted(X509Certificate[] xcs, String str) { } public void checkServerTrusted(X509Certificate[] xcs, String str) { } }; ctx.init(null, new TrustManager[] { tm }, null); SSLSocketFactory ssf = new SSLSocketFactory(ctx); ssf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); ClientConnectionManager ccm = httpClient.getConnectionManager(); SchemeRegistry registry = ccm.getSchemeRegistry(); registry.register(new Scheme("https", 443, ssf)); } catch (KeyManagementException ex) { throw new RuntimeException(ex); } catch (NoSuchAlgorithmException ex) { throw new RuntimeException(ex); } } }